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.
Last updated
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.
npm ls -g --depth 0If @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#
node --versionUpgrade 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:
format: android-xml
path: app/src/main/resThe 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:
format: i18next-json
path: locales
layout: namespacedExit 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:
which stringlaneCheck 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.
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;--forcereplaces 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:
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:
npm install -g @stringlane/cliStill stuck#
Email 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.
Translate With Your Own Provider Key
Next →The stringlane CLI