# CLI Troubleshooting

> Command not found, no localization files detected, exit code 2, a stale plan, a busy project, an MCP server that will not start, and a CI runner with no writable home directory.

Source: https://stringlane.app/docs/cli/troubleshooting
Last updated: 2026-09-14

## `stringlane: command not found`

The package installs a binary onto your `PATH`, so this means either the install did not happen or the shell has not picked it up.

```sh
npm ls -g --depth 0
```

If `@stringlane/cli` is not listed, install it: `npm install -g @stringlane/cli`. If it is listed, open a new shell — a running one does not re-scan `PATH`.

To use it without installing: `npx @stringlane/cli check .`

## `Node 22 or newer is required`

```sh
node --version
```

Upgrade Node, or use a version manager to select 22 or later for this project. There is nothing else to satisfy: the CLI ships as one file with no dependencies.

## No localization files were found

StringLane says this rather than reporting an empty project as a healthy one. Two causes.

**Detection guessed wrong.** Run `stringlane init .` and read what it proposes without accepting it. If the `format` or `path` is not right, write the correct one:

```yaml
format: android-xml
path: app/src/main/res
```

**The layout is not a standard one.** i18next in particular has two shapes; if each locale is a directory of namespace files rather than one file, say so:

```yaml
format: i18next-json
path: locales
layout: namespaced
```

## Exit code 2

The command could not run, which is deliberately distinct from exit 1. Run it without `--json` and read the message: it names the cause. Common ones are a `stringlane.yaml` that does not parse, a `path` pointing at a directory that does not exist, and an unrecognised flag.

`--fail-on` cannot turn a 2 into a 0, by design.

## `STALE_PLAN`

A file the plan could touch changed between the plan being made and `apply` running: one of your source files, one of the target files, or `stringlane.yaml` itself. The message names what moved.

This is not an error to work around. Re-run `stringlane plan` and hand the agent the new one — the alternative is overwriting an edit that StringLane never read.

Note that a *context* change is enough. Adding a description or changing `productContext` invalidates affected items even though the source English did not move, because a translation made without that context is not the same translation.

## `PROJECT_BUSY`

Another `apply` holds the per-project lock. Wait for it.

If you are certain nothing is running — a previous run was killed, say — `--force-unlock` takes the lock and reports that it did. StringLane already reclaims a lock left by a dead process on its own, and reports that as a warning rather than doing it silently, so `--force-unlock` is only for the case where the process id has since been reused by something unrelated and the lock therefore looks alive forever.

## `apply` refuses without a terminal

```
refusing to write your localization files without confirmation.
stdin is not a terminal, so there is nobody to ask — pass --yes to confirm up front.
```

Working as intended. If this is your own script and you mean it, pass `--yes`. If this is CI, reconsider: a pipeline that writes translations commits work nobody read. Gate on `check` instead.

## The MCP server does not appear in my agent

**Check the CLI is reachable from the host.** A host launched from a GUI does not inherit the `PATH` your terminal has. Either install globally so it lands somewhere the system path already covers, or put the absolute path in the config:

```sh
which stringlane
```

**Check you restarted the host.** MCP servers are read at startup.

**Check the entry is where the host reads it, and under the key it reads.** `stringlane setup mcp --host <host>` prints the exact file and the entry in that host's own shape. This is the failure it exists to prevent: the eight known hosts want the entry under four different container keys, and one under the wrong key is not an error on any of them — the host starts, lists no StringLane tools, and says nothing about why. See [Agent hosts](/docs/cli/agent-hosts).

**Confirm it is really connected.** Ask the agent which locales the project has. If it answers by reading files itself rather than by calling `inspect_project`, the server is not attached.

## `setup mcp` refuses to write

It refuses rather than guessing, in three cases, and each is recoverable:

- **the file is not valid JSON** — it will not replace a config it could not read, because that file holds every other MCP server you have set up. Fix the JSON;
- **the file is a symbolic link** into a dotfiles repository — replacing it would turn your link into a plain file. Edit the real file, or add the entry by hand;
- **StringLane is already configured there with a different entry** — it shows you both and waits for `--force`. An entry written by an older version names one project directory; `--force` replaces it with the one that covers them all.

## CI: no writable home directory

StringLane keeps a small amount of its own state outside your repository, in the usual per-user location for the platform. On a runner or in a container where that has nowhere to go, point it somewhere writable:

```sh
export STRINGLANE_STATE_HOME="$RUNNER_TEMP/stringlane"
```

It must be **absolute**. A relative value is ignored rather than honoured, because the state would otherwise land wherever the command happened to be started from.

## The Windows plugin resolver does not run

Expected. The plugin's bundled resolver is a POSIX shell script. Install the CLI yourself once and the MCP server and hooks behave identically:

```sh
npm install -g @stringlane/cli
```

## Still stuck

Email [support@stringlane.app](mailto:support@stringlane.app) with the command you ran and the output. `stringlane check . --json` is the most useful thing to attach: it names the format, the detected config and every finding, and it contains no source strings beyond the keys involved.

## Frequently asked questions

### Why does my agent not see the StringLane MCP tools?

Usually because the process that starts the server cannot find stringlane on its PATH — a host launched from a GUI does not inherit the PATH your shell has. Install the CLI globally, or give the absolute path as the command in the MCP entry, then restart the host.

### Why does stringlane say no localization files were found?

Either the format or the path is wrong, or the project layout is not one detection recognises. Run stringlane init to see what it detects, and set format and path in stringlane.yaml explicitly if the guess is wrong.
