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".
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
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]
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)
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
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
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
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
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
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
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
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
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.