Hidden Assumptions in nx

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

Every codebase relies on things it never checks. Most of them are routine. CodeSea looked at nrwl/nx 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

When disk space runs low during cache writes, tasks may fail silently or corrupt cached artifacts, causing subsequent builds to restore invalid results or fail unexpectedly

Worth your attention first

Nx may rebuild unnecessarily when files are touched but not changed, or miss rebuilds when content changes but timestamps don't update, leading to stale builds in production

Worth your attention first

On Windows or when files are locked by IDEs/processes, hash computation fails causing cache misses and forcing unnecessary rebuilds, or crashes with EACCES/EBUSY errors

Show everything (12 more)
Scale

Assumes NX_PARALLEL environment variable or tasksRunnerOptions.parallel number will not exceed system memory capacity when spawning concurrent task processes

If this fails: Setting parallel tasks too high can cause OOM kills of task processes, leading to cryptic failures and incomplete builds without clear error messages about resource exhaustion

packages/nx/src/tasks-runner/default-tasks-runner.ts
Contract

Assumes plugin createNodes functions return consistent project configurations between invocations with same inputs — doesn't validate that plugins are deterministic

If this fails: Non-deterministic plugins cause project graph to change randomly between runs, invalidating caches unpredictably and causing inconsistent build behavior across team members

packages/nx/src/project-graph/plugins/plugin-manager.ts
Ordering

Assumes task outputs can be safely restored from cache without considering order of restoration — restores all cached files simultaneously

If this fails: If cached files have interdependencies or specific restoration order requirements, parallel restoration may create partially-valid build states or overwrite files incorrectly

packages/nx/src/tasks-runner/cache.ts
Domain

Assumes file paths are normalized consistently across different operating systems when computing task hashes — may use platform-specific path separators in hash inputs

If this fails: Same source code produces different task hashes on Windows vs Unix, preventing cache sharing in mixed CI environments and forcing redundant rebuilds

packages/nx/src/hasher/task-hasher.ts
Resource

Assumes all TypeScript/JavaScript files in the workspace can be parsed by the TypeScript compiler without memory limits — loads entire files into memory for dependency analysis

If this fails: Very large source files or workspaces with thousands of files may cause Node.js to run out of heap memory during graph analysis, crashing with out-of-memory errors

packages/nx/src/project-graph/project-graph-builder.ts
Temporal

Assumes git base commit exists and is accessible when calculating affected projects — uses affected.defaultBase configuration or git merge-base

If this fails: In shallow clones or when base commit is not available, affected calculation fails causing all projects to be marked as affected, destroying incremental build benefits

packages/nx/src/project-graph/affected/affected-project-graph-builder.ts
Environment

Assumes tsquery can successfully parse and modify any JavaScript/TypeScript file structure in cypress.config files — directly manipulates AST without validation

If this fails: Malformed or unusual cypress config syntax causes AST parsing to fail, corrupting config files or failing silently without applying necessary e2e configuration changes

packages/cypress/src/utils/config.ts:addDefaultE2EConfig
Contract

Assumes Task objects will always have valid project and target strings that correspond to real projects and targets in the workspace — no validation against current project graph

If this fails: Stale or invalid tasks referencing deleted projects/targets get executed, causing runtime errors or executing against wrong project configurations

packages/nx/src/config/task-graph.ts
Scale

Assumes NX_CACHE_DIRECTORY path length will not exceed filesystem limits and that nested cache directory structures won't hit path length constraints on Windows (260 character limit)

If this fails: Deep project hierarchies or long project names cause cache writes to fail with ENAMETOOLONG errors, disabling caching entirely for affected projects

packages/nx/src/utils/cache-directory.ts
Environment

Assumes commandsObject.argv will successfully parse command line arguments and that Node.js environment supports the expected argument format

If this fails: Unusual shell environments or argument parsing edge cases may cause workspace creation to fail silently or with confusing error messages

packages/create-nx-workspace/bin/index.ts
Domain

Assumes plugin names in plugins array correspond to actual installable npm packages or local plugin files — no validation that plugins exist before attempting to load

If this fails: Typos in plugin names or missing plugin dependencies cause workspace initialization to fail with unclear module resolution errors

packages/nx/src/config/nx-json.ts
Temporal

Assumes file system watcher state remains consistent between file change events — doesn't handle rapid successive changes to the same file

If this fails: Fast file modifications may cause incomplete change detection, missing some affected projects in incremental builds or causing race conditions in graph updates

packages/nx/src/file-utils.ts

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

Full analysis of nrwl/nx →

Frequently Asked Questions

What does nx assume that could break in production?

The one most likely to cause trouble: Assumes sufficient disk space to store all task outputs in cache without checking available disk space — uses NX_CACHE_DIRECTORY or default .nx/cache directory If this fails, When disk space runs low during cache writes, tasks may fail silently or corrupt cached artifacts, causing subsequent builds to restore invalid results or fail unexpectedly

How many hidden assumptions does nx have?

CodeSea found 15 assumptions nx relies on but never validates, 5 of them critical, spanning Resource, Temporal, Environment, Scale, Contract, 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.