Hidden Assumptions in blitz

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

Every codebase relies on things it never checks. Most of them are routine. CodeSea looked at blitz-js/blitz 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 PrismaClient is undefined, null, or not a constructor, the `new EnhancedPrisma()` call will throw a runtime error that crashes the application on database access

Worth your attention first

In environments where localStorage is disabled (private browsing, storage quota exceeded), authentication state synchronization fails silently across browser tabs, causing inconsistent login states

Worth your attention first

If the token contains valid JSON but missing userId/role fields, components using useCurrentUser will receive malformed user data and may crash when accessing expected properties

Show everything (9 more)
Temporal

The 100ms setTimeout delay is sufficient for Next.js routing to complete before clearing React Query cache, but this timing is hardcoded without considering slow devices or heavy page loads

If this fails: On slow devices or complex pages, authentication queries may start before the cache is cleared, leading to stale authentication data being displayed or authorization errors on protected pages

packages/blitz-rpc/src/query/react-query/index.ts:resetQueryClient
Contract

Dynamic import promises will always resolve to modules with the expected export names (dev, build, generate, etc.), but no validation exists for the imported module structure

If this fails: If a command module is corrupted or renamed its exports, CLI commands fail with confusing 'not a function' errors instead of clear 'command not found' messages

packages/blitz/src/cli/index.ts:commands[blitzCommand]
Environment

If tsconfig.json exists, it contains valid JSON with properly structured compilerOptions.paths, but only checks file existence

If this fails: Malformed tsconfig.json files cause Jest setup to fail with obscure JSON parsing errors, making it unclear that the TypeScript configuration is the root cause

packages/blitz-next/jest/index.js:tsConfigPath
Resource

Canceling and resetting all React Query queries will complete within reasonable time, but no timeout or error handling exists for stuck queries

If this fails: If some queries become stuck or unresponsive, the cache reset operation hangs indefinitely, preventing users from logging out completely and leaving the app in an inconsistent state

packages/blitz-rpc/src/query/react-query/index.ts:queryClient.resetQueries
Scale

The BadBehavior observable pattern can handle unlimited subscribers across multiple browser tabs without memory leaks, but no cleanup or subscription limits exist

If this fails: Applications with many tabs or long-lived sessions may accumulate memory leaks from uncleaned observable subscriptions, eventually degrading browser performance

packages/blitz-auth/src/client/index.tsx:BadBehavior.observable
Ordering

Next.js router context is available and stable during error boundary rendering, but no validation exists that router object contains expected properties

If this fails: During navigation errors or router resets, the error boundary may try to access undefined router properties, causing additional errors that mask the original problem

packages/blitz-next/src/error-boundary.tsx:withRouter
Domain

The currentUser object returned by useCurrentUser hook always has string-type id and role properties when user is authenticated, but the component directly renders these without type checking

If this fails: If the authentication system returns user objects with numeric IDs or null roles, the JSX will display '[object Object]' or empty values, confusing users about their login status

apps/toolkit-app/src/pages/index.tsx:currentUser.id
Environment

NODE_ENV is properly set to 'production' in production environments to enable React Query retry logic, but no fallback exists for undefined NODE_ENV

If this fails: In deployment environments where NODE_ENV is not set, React Query retries are disabled even in production, causing network-failure-sensitive operations to fail immediately instead of retrying

packages/blitz-rpc/src/query/react-query/index.ts:process.env.NODE_ENV
Temporal

Storage events from localStorage.setItem() in other tabs fire synchronously and reliably, but browser implementations may throttle or batch these events

If this fails: In browsers that throttle storage events or during high tab activity, authentication state changes may not synchronize immediately between tabs, creating temporary inconsistencies in login status

packages/blitz-auth/src/client/index.tsx:window.addEventListener

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

Full analysis of blitz-js/blitz →

Frequently Asked Questions

What does blitz assume that could break in production?

The one most likely to cause trouble: enhancePrisma() returns a constructor that can be called with `new` to create a Prisma client instance, but no validation exists that PrismaClient is actually a constructable class If this fails, If PrismaClient is undefined, null, or not a constructor, the `new EnhancedPrisma()` call will throw a runtime error that crashes the application on database access

How many hidden assumptions does blitz have?

CodeSea found 12 assumptions blitz relies on but never validates, 3 of them critical, spanning Contract, Environment, Shape, Temporal, Resource, Scale, Ordering, Domain. 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.