Repository navigation
fix(signer): serialize object payloads in host error messages - #423
Merged
Merged
Conversation
formatError fell back to String() for a tag whose value is a plain
object, and for a tagless object with neither reason nor message, so a
product-account rejection logged as "Host rejected product account
request: Domain → V1 → Unknown ([object Object])" and the host's payload
was lost from the message and the log line.
Object payloads are now serialized as JSON: bigints as strings, byte
arrays as hex with long ones cut to their first 64 bytes (so the fields
after a blob survive the 500-character cap), a nested Error as its name,
message and cause (JSON.stringify drops them), cycles cut. A { reason }
payload under a tag reads as its reason, as a tagless one already did.
📦 Bundle size impactComparing
Thresholds — 🟡 ≥10% or ≥5.0 KB · 🟠 ≥20% or ≥15.0 KB (bundled). Percentage only applies once the baseline is ≥ 10 KB. Informational — this check never blocks merge. |
TarikGul
reviewed
Oct 5, 2026
describeValue rebuilt a nested Error from name, message and cause, so an RPC error's code and data never reached the message, though they are usually what the log needs. It now copies the error's own enumerable fields too, after name and message and before cause, so a long cause cannot push them past the 500-character cut. The WeakSet also marks a shared object that is not a cycle, so its "[seen]" label read like a cycle. Rename it "[repeated]", which fits both. Tracking only the enclosing objects instead would print a shared object once per parent, which grows exponentially on a graph that shares heavily; the WeakSet keeps the walk linear.
TarikGul
approved these changes
Oct 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
formatErrorinpackages/signer/src/providers/host.tsbuilds the message of everyHost rejected … requesterror and thefailed to get product accountlog line. When a tag's value is a plain object, or a tagless error has neitherreasonnormessage, it falls back toString(). So the payload prints as[object Object]. A Coffer deployment on the paseo.li web host logged:The host's reason for rejecting the request is lost from both the message and the log line.
HostRejectedError.causestill holds it, but only callers that log the error object itself can see it.Change
A local
describeValuereplaces the twoString()fallbacks. It returns:Erroras its name, message and cause, whichJSON.stringifywould otherwise drop;[seen], which also cuts cycles;A
{ reason }payload under a tag now reads as its reason (V1 → Unknown → no account), as a tagless{ reason }already did. Every output that was not[object Object]before is unchanged.Tests
Seven new cases in the in-source
formatErrorsuite:Domain → V1 → Unknownnesting with an object payload;reasonpayload under a tag;Errorwith a cause.Checks:
pnpm --filter @parity/product-sdk-signer testpasses 156 tests,typecheckexits 0, andpnpm checkis clean.The changeset is a
patchfor@parity/product-sdk-signer, parked inpending-changesets/.🤖 Generated with Claude Code