Hidden Assumptions in remix
13 assumptions this code never checks · 5 critical · spanning Shape, Environment, Ordering, Domain, Contract, Scale, Resource, Temporal
Every codebase relies on things it never checks. Most of them are routine. CodeSea looked at remix-run/remix 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 the stored context has wrong shape (missing required properties, wrong types), the cast succeeds but downstream code crashes with property access errors like 'Cannot read property of undefined'
In non-Node environments (browsers, Deno, Bun) or Node versions < 14.17, the import throws 'module not found' or AsyncLocalStorage is undefined, breaking the entire middleware
When comparing expiresAt with current time across different server timezones or daylight saving transitions, tokens may be considered expired when valid or valid when expired
Show everything (10 more)
asyncContext middleware executes before any middleware that calls getContext(), but no ordering constraints are enforced
If this fails: If getContext() is called before asyncContext runs, it throws 'No request context found' error, but this dependency is only discoverable at runtime
packages/async-context-middleware/src/lib/async-context.ts:asyncContext
All AuthScheme implementations return AuthSchemeResult with consistent identity types, but no runtime type checking exists between schemes
If this fails: If one scheme returns identity as string while another returns object, handlers accessing context.get(Auth).identity crash with type errors when switching auth methods
packages/auth-middleware/src/lib/auth.ts:AuthScheme.authenticate
1024 byte default compression threshold works for all response types, but small JSON responses under this limit bypass compression even when highly compressible
If this fails: API endpoints returning repetitive JSON data (like arrays of similar objects) miss significant compression opportunities, increasing bandwidth usage and response times
packages/compression-middleware/src/lib/compression.ts:threshold
Content-Type header always contains valid MIME type format 'type/subtype', but malformed headers are not validated
If this fails: If Content-Type header contains malformed values like 'invalid' or 'text', mediaType.split(';')[0] produces unexpected results and compression may apply to inappropriate responses
packages/compression-middleware/src/lib/compression.ts:filterMediaType
compressResponse can handle any response body size in memory, but no size limits or streaming checks exist
If this fails: Attempting to compress very large response bodies (like file downloads) causes out-of-memory errors or blocks the event loop during compression
packages/compression-middleware/src/lib/compression.ts:compressResponse
Cookie secrets array represents rotation order with newest first, but no validation ensures secrets don't repeat or become empty
If this fails: If secrets array becomes empty or contains duplicates, cookie signing fails silently or produces predictable signatures, breaking authentication security
packages/cookie/src/lib/cookie.ts:secrets
Cookie expires Date uses browser's local timezone interpretation, but server-side Date creation uses server timezone
If this fails: When server and client are in different timezones, cookies expire at unexpected times - either too early (user gets logged out) or too late (security risk)
packages/cookie/src/lib/cookie.ts:expires
Cross-origin protection checks execute after CORS middleware has set appropriate headers, but middleware ordering is not enforced
If this fails: If COP runs before CORS, legitimate preflight OPTIONS requests get blocked as cross-origin attacks, breaking CORS-enabled APIs
packages/cop-middleware/src/lib/cop.ts:check
Trusted origins are exact string matches including protocol and port, but origin normalization rules are not documented
If this fails: Origins like 'https://example.com:443' don't match 'https://example.com' even though browsers normalize them as identical, causing legitimate requests to be blocked
packages/cop-middleware/src/lib/cop.ts:trustedOrigins
Signal<string> objects maintain referential stability during data transformations, but array operations create new signal instances
If this fails: When sortAsc() rebuilds signal rows, existing component subscriptions to old signal instances become orphaned, causing UI to stop updating until full re-render
packages/component/bench/frameworks/preact-signals/index.tsx:Row
See the full structural analysis of remix: the pipeline, data models, and system behavior that put these assumptions in context.
Full analysis of remix-run/remix →Frequently Asked Questions
What does remix assume that could break in production?
The one most likely to cause trouble: AsyncLocalStorage.getStore() returns the exact same RequestContext type that was stored, but the function casts it blindly with 'as AsyncRequestContext' without runtime validation If this fails, If the stored context has wrong shape (missing required properties, wrong types), the cast succeeds but downstream code crashes with property access errors like 'Cannot read property of undefined'
How many hidden assumptions does remix have?
CodeSea found 13 assumptions remix relies on but never validates, 5 of them critical, spanning Shape, Environment, Ordering, Domain, Contract, Scale, Resource, Temporal. 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.