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

# Troubleshooting

> Common setup errors and the command that fixes each.

Run `outerlayer doctor` first. Most failing checks name their fix. The entries below are grouped by the message or symptom you see.

A build that fails or never starts on a host is covered in [Troubleshoot builds](/troubleshoot-builds).

## Signing in and choosing a factory

### `outerlayer login` keeps waiting, or says the link expired

In a terminal, `login` prints a link and a code, then waits. Open the link, check the dashboard shows the same code, and approve it. The link has a time limit. After it, you see `the login link expired; run outerlayer login again`. A login someone declined ends with `the login was denied`.

When stdout is not a terminal, as in an agent's shell, `login` prints one JSON line with `"status": "waiting"` and exits 75. Approve the link it names, then run the `check` command from that line, `outerlayer login --check <id>`. Exit 75 again means it is still waiting. See [`outerlayer login`](/reference/cli-cloud#outerlayer-login).

### `login` exits 2 with "--url and --app-id apply only to a piped key"

Browser login takes its gateway address from the dashboard, so it refuses both flags. Drop them, or pipe a key in with them.

### `login` says it "is waiting for an API key on stdin"

Something left stdin open, so `login` waits for a key. Close stdin, or run it with nothing piped to sign in by browser.

### `outerlayer connect` exits 2: "has no link to … yet"

The connection is saved, but the repository is not linked to the factory. The message prints the factory's Work page link. Open it, choose **Connect GitHub repository** and grant the App access, then **Link repository**. Run `outerlayer connect` again. See [Connect a repository](/connect-repository).

### A command says no gateway URL or address is saved

There is no default gateway, so a cloud command with no URL refuses. You see `missing --url`, `no gateway address is saved`, or, from `mcp serve`, `no gateway URL`. Run `outerlayer login`, which saves the address from the dashboard. Or set `OUTERLAYER_URL`, or pass `--url`. See [Credential resolution](/reference/cli#credential-resolution).

### A command says credentials are missing

`sync`, `work` and `emit` refuse when no credential is saved. The message starts with `missing`, then names each value it lacks, such as `missing --url, a login or OUTERLAYER_API_KEY, --app-id`. Run `outerlayer login` with nothing piped and approve the link. Then run `outerlayer connect` to choose a factory.

If it says you are logged in but no factory is chosen, run `outerlayer connect`, or pass `--app-id`. To use a key you already have, pipe it in:

```bash theme={"system"}
echo "$OUTERLAYER_KEY" | outerlayer login --url https://api.outerlayer.ai --app-id <factory-id>
```

Never pass the key on the command line. The `--api-key` flag is deprecated. Pipe the key to `login`, or set `OUTERLAYER_API_KEY`. See [API keys](/api-keys).

### Commands use a factory key instead of your login

A factory key always wins over a login, whether it comes from `OUTERLAYER_API_KEY` or `apiKey` in `~/.outerlayer/config.json`. Run `outerlayer doctor`. A **Factory key** check means a key is in use, and its detail names where it came from. To use your login instead:

* `unset OUTERLAYER_API_KEY`, and remove it from your shell profile.
* Delete the `apiKey` field from `~/.outerlayer/config.json`.

After a browser login, `login` warns when an `apiKey` is saved in that file. It does not warn about `OUTERLAYER_API_KEY`.

### "not authorized — the API key is unknown, expired, or bound to a different factory"

The key was revoked, or the factory id you gave `login` is a different factory. Check **Settings → General** for the Factory Id and **Settings → API keys** for the key. Then run `login` again. With a login, the message says the login expired or was revoked: run `outerlayer login`.

## Sessions and sync

### sync says "not launched with OUTERLAYER\_WORK"

The sessions were started without the variable. They stay on this machine and never upload. Start a new session on the item's number. `work build --issue` adds the issue to the Work page if it is not there yet, and prints the item's number:

```bash theme={"system"}
npx @outerlayer/cli work build --issue 42 --local   # prints the item's number, say #7
OUTERLAYER_WORK=7 claude
```

See [Launch a session](/launch-a-session).

### `outerlayer sync` exits 2

The server rejected at least one session. The first 10 rejects are listed under the summary, then `… and N more rejects`. Each shows its reason, such as `session belongs to another work item`. A rejected session is not retried. Fix the cause, then run `outerlayer sync --all` to send it again. See [`outerlayer sync`](/reference/cli-cloud#outerlayer-sync).

### The session started but it is not on the work item's page

Read `~/.outerlayer/spool/hook-errors.log`. The usual reasons:

* `OUTERLAYER_WORK` named an issue (`#42`) rather than an item number. Run `work build --issue 42 --local` to get the item's number, then launch on it.
* The number names no item on this factory, or a withdrawn one. Check it on the Work page.
* The gateway could not be reached. The link retries a few times, then gives up.

Start a new session once the cause is fixed. A running session cannot be linked afterwards.

### Cursor sessions are not captured

Reading Cursor's chats needs Node 22.5 or later. On older Node, sync skips Cursor and still syncs every other agent. Upgrade Node. See [Supported agents](/launch-a-session#supported-agents).

### The status line shows only the session cost

The daemon is not running. The cross-agent total comes from a file it keeps fresh. Start it in a terminal you keep open, or under a login agent:

```bash theme={"system"}
outerlayer daemon
```

### Hooks stopped firing after a Claude Code update

Run `outerlayer doctor` and read **Hooks installed** and **Settings JSON valid**. **Hooks installed** also fails when a hook runs a file that no longer exists, such as a cleared npx cache. Install the CLI globally, then reinstall the hooks. `init` backs the settings file up first.

```bash theme={"system"}
npm i -g @outerlayer/cli
outerlayer init --local
```

## Work items and review

### work build says the repository "is not a workpiece of this factory"

The error code is `repository_not_connected`. `outerlayer work build --issue <n>` uses the checkout's remote, and that repository must be linked to the factory. Link it on the factory's **Settings → General**, or from the setup panel on the Work page. Or pass `--repo owner/name` for a repository that is linked. See [Connect a repository](/connect-repository).

### `work claim` is refused with `work_item_not_requested`

An implement claim needs an unused build request. Ask for one with `outerlayer work build --issue <n>`, then claim again. An amend claim needs a thread waiting on an agent since the last attempt. Hand a thread to the agent on the item's page first. See [`work claim`](/reference/cli-work#outerlayer-work-claim-renew-release).

### `work comment` is refused with `verdict_needs_person`, `verdict_on_criterion` or `artifact_needs_attach`

* `verdict_needs_person`: `--pass` and `--fail` are a person's judgment. Run them yourself, outside the agent session, with your own login, not a key.
* `verdict_on_criterion`: a verdict is on the whole item. Drop `--criterion`, and leave a note on a criterion with a plain comment.
* `artifact_needs_attach`: `--artifact` is accepted only with `--attach` and `--criterion`. Nothing was stored.

See [`work comment`](/reference/cli-work#outerlayer-work-comment).

### `emit criteria` is refused (409)

The item already has a recorded list, and only a person may replace it. Run the command yourself, outside the session, with your own login. To let sessions replace it, set `criteria: { replace: anyone }` in `.outerlayer/policy.yaml` on the default branch. See [`emit criteria`](/reference/cli-emit#outerlayer-emit-criteria).

### No checks run on your pull requests

The factory reads `.outerlayer/` from the default branch. Until `init`'s files are merged there, no check runs. Commit `.outerlayer/` and merge it. See the [Quickstart](/quickstart).

### An artifact refuses to emit inside a session

The session has no launch record, so a spooled artifact would never upload. Start the session with `OUTERLAYER_WORK`, or run the emit from a plain shell with `--pr`.

### The evidence comment shows a policy error row

`.outerlayer/policy.yaml` or a validator file on the base branch failed to load. The row names the file and the problem. A validator loads whole or not at all. See [Policy and validators](/policy-and-validators).

## Hosts and the GitHub App

### `outerlayer doctor` says the installation "has not accepted" a permission

Builds need a permission the GitHub App installation has not accepted yet. An owner of the installation accepts it on the settings page doctor links. If doctor says the App does not request it, the App's own settings must add it first. See [Check what each repository is missing](/github-app-and-build-tokens#check-what-each-repository-is-missing).

### A runner key is refused on a new machine

A runner key is bound to the host key of the first machine that used it. Elsewhere, the runner reports the key is "bound to another host's key". A member clears the binding with **Clear host key** on **Settings → API keys**. The next claim binds the new host. See [Moving a runner to a new host](/run-a-host-as-a-service#moving-a-runner-to-a-new-host).

### A build fails with `agent_credential_missing` or `disk_limit_exceeded`

* `agent_credential_missing`: the runner has no Claude credential. Give it one and restart the runner.
* `disk_limit_exceeded`: the build outgrew `runner.build.disk`. Raise it.

See [Outcomes and reasons](/troubleshoot-builds#outcomes-and-reasons).


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