Hidden Assumptions in trpc

12 assumptions this code never checks · 5 critical · spanning Shape, Contract, Ordering, Domain, Resource, Temporal, Environment, Scale

Every codebase relies on things it never checks. Most of them are routine. CodeSea looked at trpc/trpc and picked out the few most likely to cause trouble. The full list is just below.

Most of what this code assumes is routine. These 3 are the ones most likely to cause trouble here. The rest are minor; they're under "Show everything".

Worth your attention first

If server returns malformed error responses with missing or incorrectly-typed 'data' fields, clients receive TRPCClientError with undefined/invalid this.data property, breaking error handling code that expects specific error data structures

Worth your attention first

If opts.config() returns a malformed client or clientCallTypeToProcedureType returns unexpected procedure types, the proxy crashes at runtime with 'undefined is not a function' when trying to call client[procedureType]

Worth your attention first

If called with empty path array, pathCopy.pop() returns undefined, causing action to be undefined and procedureType lookup to fail, resulting in runtime errors when trying to access client[undefined]

Show everything (9 more)
Domain

query object passed to querySerializer contains only serializable values that URLSearchParams can handle, but never validates value types - assumes no nested objects, functions, or circular references

If this fails: If query contains complex objects, functions, or circular references, URLSearchParams silently converts them to '[object Object]' or throws, producing invalid query strings that break API calls

packages/openapi/src/heyapi/index.ts:createTRPCHeyApiClientConfig
Resource

React Query's cache can handle the generated query keys without memory issues - assumes keys are reasonably sized and don't contain large objects that would bloat the cache

If this fails: If procedures have large input objects as parameters, query keys become massive and consume excessive memory in React Query's cache, potentially causing browser crashes or severe performance degradation

packages/react-query/src/index.ts:getQueryKey
Temporal

opts.config() returns the same configuration on every call within a single request, allowing safe caching with React's cache() function - assumes config is static during request lifecycle

If this fails: If config changes between calls (e.g., based on request headers or dynamic context), cache returns stale client configurations, causing requests to use wrong endpoints, auth tokens, or transforms

packages/next/src/app-dir/server.ts:getClient cache
Environment

AWS Lambda runtime provides the expected APIGWContext object structure and event formats matching LambdaEvent interface, but never validates the runtime environment or context shape

If this fails: If deployed to non-AWS environments or newer Lambda runtime versions change context structure, planner.request and planner.path extraction fails silently, causing request routing to break without clear error messages

packages/server/src/adapters/aws-lambda/index.ts:awsLambdaRequestHandler
Scale

TypeScript program can load and analyze all source files in memory simultaneously - assumes codebase size fits in available memory without considering large monorepos or projects with thousands of files

If this fails: On large codebases, getProgram() consumes excessive memory and may crash with out-of-memory errors, making the upgrade tool unusable for enterprise-scale projects

packages/upgrade/src/bin/index.ts:getProgram
Contract

fetchRequestHandler from @trpc/server/adapters/fetch expects a standard Request object and returns a Response, but never validates that Bun's fetch API contract matches Node.js/browser standards

If this fails: If Bun's Request/Response implementations have subtle differences from standard Web APIs, request parsing or response formatting may fail in production, causing silent data corruption or unexpected errors

examples/bun/src/index.ts:fetchRequestHandler
Environment

Cloudflare Workers runtime provides the expected WorkerEntrypoint class and supports standard fetch RequestHandler pattern, but never validates runtime capabilities or API availability

If this fails: If deployed to older Cloudflare Workers runtime or if WorkerEntrypoint API changes, the service fails to initialize properly, causing all tRPC requests to return 500 errors without clear debugging information

examples/cloudflare-workers/src/index.ts:TRPCCloudflareWorkerExample
Domain

OpenAPI schema format values 'date-time' and 'date' always map correctly to JavaScript Date objects, but doesn't account for timezone handling, invalid date strings, or different date serialization formats

If this fails: When API returns dates in unexpected formats or timezones, the generated client code creates invalid Date objects, causing date calculations to produce wrong results or NaN values in UI components

packages/openapi/src/heyapi/index.ts:createTRPCHeyApiTypeResolvers
Contract

Error responses follow the exact structure with nested error.code and error.message properties, but doesn't validate that the full error shape matches what downstream error handlers expect (e.g., missing error.data)

If this fails: Partial error responses that pass basic validation but lack expected error.data fields cause error boundaries and user error handling to receive incomplete error information, leading to generic error messages instead of specific user-facing errors

packages/client/src/TRPCClientError.ts:isTRPCErrorResponse

See the full structural analysis of trpc: the pipeline, data models, and system behavior that put these assumptions in context.

Full analysis of trpc/trpc →

Frequently Asked Questions

What does trpc assume that could break in production?

The one most likely to cause trouble: opts.result.error shape matches inferErrorShape<TRouterOrProcedure> but only validates that obj.error.code is a number and obj.error.message is a string - ignores the 'data' field which contains the actual error payload that clients depend on for error handling If this fails, If server returns malformed error responses with missing or incorrectly-typed 'data' fields, clients receive TRPCClientError with undefined/invalid this.data property, breaking error handling code that expects specific error data structures

How many hidden assumptions does trpc have?

CodeSea found 12 assumptions trpc relies on but never validates, 5 of them critical, spanning Shape, Contract, Ordering, Domain, Resource, Temporal, Environment, Scale. Most are routine — the analysis flags the two or three most likely to actually bite.

What is a hidden assumption?

Something the code depends on but never checks: a data shape, an ordering, an environment condition, a scale limit, or a contract with another service. It holds until the world it runs in changes, then fails silently.