> ## Documentation Index
> Fetch the complete documentation index at: https://isox.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshooting

> Resolve workspace discovery, executor loading, build, configuration, and CI selection problems.

## Start with verbose output

Repeat the failing command with `--verbose` to include debug logs and error stacks:

```sh theme={null}
npx isox build web --verbose
```

Check the runtime with `node --version`. Use Node.js 24 or 26+ when running the
repository and Vitest plugin; Vitest 5 excludes Node.js 25.

## CLI not found or the wrong package runs

Install `@isox-sh/cli` in your workspace before running `npx isox`:

```sh theme={null}
npm install --save-dev @isox-sh/cli
npx isox --help
```

The npm package is `@isox-sh/cli`, while its executable is `isox`. For pnpm and
Yarn installations, use `pnpm exec isox` or `yarn isox`. See
[installation options](https://isox.sh/docs/getting-started.md#install).

## Workspace not found

Isox searches from the current directory upward for `isox.json`. Run
`npx isox init` at the intended workspace root, then run commands from that
directory or its descendants. A marker in a nested directory creates a separate
workspace boundary.

`init` refuses to overwrite an existing marker. Edit that file directly when
changing settings in an initialized workspace.

## Project or command not found

Check that the project has a `project.json` with a unique name and that the
command is defined under `targets`. Check that its path is not excluded by
`.gitignore` or `.isoxignore`, symlinked, or inside a nested workspace. Discovery
uses cached definitions for single-project commands. Refresh them after edits:

```sh theme={null}
npx isox reset
npx isox build web
```

Names are case-sensitive. The directory name is used when `name` is omitted.
For a command named `init`, `add`, `run`, `reset`, `affected`, `plan`, or `run-many`, use
`isox run web:reset` (substituting your command) to avoid the CLI's reserved names.

## Why does run-many rebuild the workspace every time?

`run-many` deliberately reads fresh `project.json` files and rewrites
`.isox/workspace.json` before selecting tasks. Its child commands then load that
definitions cache. This refresh does not analyze source imports. An executor such
as `js:tsc` can separately request dependency analysis and use `discovery.json`.
`affected` and `plan` also refresh project definitions on every invocation.

## Why did a comment edit change the sources SHA?

The per-project `sources` SHA in `discovery.json` fingerprints file paths,
identities, sizes and timestamps. It does not hash only imports. A body or comment
edit can invalidate that project's entry on the next dependency request.
Isox reanalyzes the project's included sources, not just the edited file;
unchanged dependency projects can still reuse their results. Tests and declaration
files count unless excluded by discovery rules or compiler output ownership.

Only dependency requests perform these checks. Ordinary command loading reads
`workspace.json` directly. Source edits do not require `isox reset`, and a valid
dependency cache does not skip compilation or other task execution.

## Why does discovery.json contain paths outside the workspace?

The `reads` entries record TypeScript module-resolution probes. A directory entry
such as `{"path":"/Users/node_modules","kind":"directory","value":false}`
means that TypeScript checked whether the directory exists and it did not.
Package lookup can check `node_modules` directories up the ancestor chain; this
does not recursively scan them. File/content and real-path probes are recorded too.

Build-time dependency analysis currently includes project test files. A test's
`require.resolve()` can therefore produce probes unrelated to the emitted build
files. These records are checked only when dependency analysis is requested.
See [cache fields and invalidation](https://isox.sh/docs/discovery-cache.md#discovery-cache).

## Executor package cannot be loaded

Install executor packages where they resolve from the workspace root. For
example, `js:tsc` requires `@isox-sh/js`:

```sh theme={null}
npm install --save-dev @isox-sh/js
```

Under pnpm, use `pnpm add -Dw @isox-sh/js` from the workspace root. Build local
plugins before using them and verify that `executors.json` points to compiled
JavaScript. The [plugin layout guide](https://isox.sh/docs/plugin-packaging.md#plugin-layout) shows the
manifest structure.

The built-in `core:run-command` falls back to the CLI's core dependency. A directly
installed workspace copy takes precedence, including when that copy is invalid.

## An option or configuration is rejected

Execution commands forward unknown flags as executor options. Check the executor's
supported options when one is rejected; each executor decides whether to validate them.
For TypeScript watch mode, use `isox build web --watch`, or put `watch: true` in a
named configuration and run `isox build web --config=watch`.

Configuration names must exist on the selected command. Overrides replace nested
objects and arrays rather than merging them recursively. See
[named configurations](https://isox.sh/docs/cli.md#named-configurations).

## TypeScript cannot resolve a workspace dependency

Build the dependency with declarations enabled before building its consumer.
The TypeScript executor remaps cross-project source aliases to built declarations
using the dependency's compiler configuration. Verify its `rootDir`, `outDir`,
and any `declarationDir` match the files it emits.

The builder validates cached dependency analysis against source metadata,
configuration and resolution inputs, and reanalyzes invalid entries. For the Isox
repository itself, `pnpm bootstrap` prepares
the CLI, executors, and prerequisite outputs from a clean checkout.

## A source file is not under `rootDir`

Keep editor and build configs separate when workspace aliases point to another
project's source. The editor config can use the workspace as `rootDir` with
`noEmit: true`; the build config can keep `rootDir: "./src"` and its own `outDir`.
Set the build target's `options.tsConfig` to that build config.

Build dependencies first with declarations enabled. `js:tsc` remaps their source
aliases to declarations during compilation. Direct `tsc` invocations do not run
this Isox remapping. Projects created with `isox init @isox-sh/js <path>` already
have separate editor and build configs. See [TypeScript setup](https://isox.sh/docs/typescript.md#usage).

## Project dependency cycle

The error lists a chain such as `app -> workspace -> app`. Check both explicit
`dependencies` and inferred relationships: imports in tests and local package
`devDependencies` count too. Selection filters, including `plan.enabled: false` and `ci=off`, do not remove graph
edges or bypass cycle validation.

For an unexpected edge through compiled output, make sure each build target's
`options.tsConfig` points to the config that declares its output directory.
For a root project, imports of root-level scripts or configuration belong to
that project. Keep repository-wide tests with the root tooling they exercise,
and keep package tests focused on their package. A root project can depend on
packages without those packages needing to depend on the root.

Affected planning reads current project definitions and infers dependencies.
`isox plan --target=test` validates that graph without running tests; `--all`
skips dependency inference.

## Affected selection is larger than expected

Changes to root manifests, lockfiles, shared TypeScript configuration, and `.github`
affect all projects. Other files outside every project are ignored unless matched
by `affected.globalFiles`. Dependencies propagate
changes to their transitive dependents before command and tag filtering.

Inspect the selection without running tasks:

```sh theme={null}
npx isox affected --target=test --base=origin/main --print-matrix
```

Use narrow `affected.globalFiles` globs for additional shared tooling and
`affected.ignoreFiles` to exclude files before global and project matching. See
[what counts as affected](https://isox.sh/docs/affected-and-ci.md#what-counts-as-affected).

## Affected selection is empty or Git history is missing

Local unstaged and staged changes require `--uncommitted`; non-ignored untracked
files require `--untracked`. Projects must have the requested command and pass
the tag filters. `plan.enabled: false` or a `ci=off` tag excludes a project from normal selection.

For CI, use a checkout with `fetch-depth: 0` in the planning job. Missing revisions
are errors. On non-PR events the actions compare against the nearest reachable
Git tag; a tag on HEAD produces an empty plan. Supply an earlier `base` or set
`affectedOnly: false` when rebuilding that release.

## A TypeScript output lock remains after a forced stop

Stop active builds and recover any needed backups from `.isox/tasks` before
running `isox reset`. Reset removes stale locks and reservations, but also deletes
those backups and all output ownership records. See
[output recovery](https://isox.sh/docs/cache-outputs.md#output-ownership-and-recovery).

Reset leaves compiled output in place. Uncached TypeScript builds preserve files
whose ownership records were removed; cacheable targets still replace their
declared output directories on the next run, including with `--skip-cache`.

## Report a reproducible issue

Include the command, verbose output, Node.js and package versions, the relevant
`project.json` and tool configuration, and a small reproduction in a
[GitHub issue](https://github.com/isox-sh/isox/issues). Remove credentials and
private environment values from logs before sharing them.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.