fix(contract): only reserve then in the handler errors map - #2117
Merged
dinwwwh merged 1 commit intoSep 30, 2026
Merged
Conversation
The errors map is not a recursive proxy, so reusing the client's RECURSIVE_CLIENT_UNWRAP_KEYS reserved more names than needed. Only `then` is read implicitly (by promise resolution); the other keys are only reached through explicit conversion or serialization of the map. Error codes such as `toString`, `valueOf`, and `toJSON` can be built from `errors` again.
Contributor
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes — narrowed error-map key reservation plus its regression tests.
- Proxy guard narrowed to
then—createORPCErrorConstructorMapnow returns the raw value only for symbols and the literal keythen, dropping theRECURSIVE_CLIENT_UNWRAP_KEYSdependency. The #2113 hang fix is preserved (the map is still non-thenable), whiletoString/valueOf/toJSON/bind/call/applybuild error constructors again. - Tests realigned — the symbol/then test keeps its
awaitassertion; theObject.prototypetest switches back totoString()and assertscode === 'toString', which is exactly the assertion that fails iftoStringis reserved again.
The one behavior deliberately reintroduced from #2113 — String(errors) can throw and JSON.stringify(errors) can again emit a synthetic toJSON error — is a conscious tradeoff argued in the PR body and is only reachable through explicit conversion/serialization. No internal caller or test relies on it.
Verified locally: pnpm vitest run packages/contract/src/error-factory.test.ts → 24 passed.
DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
More templates
@orpc/ai-sdk
@orpc/arktype
@orpc/bun
@orpc/client
@orpc/cloudflare
@orpc/contract
@orpc/experimental-effect
@orpc/evlog
@orpc/hibernation
@orpc/json-schema
@orpc/experimental-lock
@orpc/experimental-msw
@orpc/nest
@orpc/next
@orpc/node
@orpc/openapi
@orpc/opentelemetry
@orpc/pinia-colada
@orpc/pino
@orpc/publisher
@orpc/ratelimit
@orpc/server
@orpc/shared
@orpc/swr
@orpc/tanstack-query
@orpc/trpc
@orpc/valibot
@orpc/zod
commit: |
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.

The handler
errorsmap now reserves onlythen, instead of every key inRECURSIVE_CLIENT_UNWRAP_KEYSas #2113 did.thenis the only key the runtime reads on its own (promise resolution), so it is the only one that caused a real failure. The others are only reached by explicitly converting or serializing the map. This narrows the behavior change from #2113.Fixes
errors.toString(),errors.valueOf(),errors.toJSON(),errors.bind(),errors.call()anderrors.apply()build errors with those codes again.await errorsand returningerrorsfrom an async handler still settle instead of hanging.Testing
then. The Object.prototype lookup test usestoString()again and fails iftoStringis reserved.@orpc/contracttype-check pass.