paperclipai/paperclip · error · Error
device login failed: the sandbox login command errored.
Error message
device login failed: the sandbox login command errored.
What it means
Thrown by the device-login runner's catch block when the injected SandboxLoginDriver rejects during execStreaming (running `codex login --device-auth`), readFile (reading the sandbox auth.json), or the race wrapper. The runner deliberately discards the original error message because sandbox stream bytes may carry the device code/URL/token, and rethrows a fixed non-secret message (Control 1 — secret handling).
Source
Thrown at packages/adapters/codex-local/src/server/device-login-runner.ts:196
return { outcome: "cancelled", exitCode: null, promptSurfaced };
}
const exitCode = raced.exitCode;
if (exitCode !== 0) {
log("[paperclip] Device login command ended with a non-zero exit code.");
return { outcome: "failure", exitCode, promptSurfaced };
}
if (onCredential && authPath) {
const authBytes = await driver.readFile(authPath);
await onCredential(authBytes);
}
log("[paperclip] Device login command ended successfully.");
return { outcome: "success", exitCode, promptSurfaced };
} catch {
// Convert any driver error to a fixed, non-secret error. The original error
// may embed streamed bytes, so the runner never propagates its message.
throw new Error("device login failed: the sandbox login command errored.");
} finally {
// Always dispose the driver. A dispose error must not leak or mask the
// result, so the runner swallows it and logs a fixed line.
try {
await driver.dispose();
} catch {
log("[paperclip] Device login: the sandbox dispose step errored.");
}
}
}
View on GitHub (pinned to 67001ec6eb)
Solutions
- Retry the device login once — sandbox spawn failures are often transient.
- Verify the sandbox image is reachable and the SandboxLoginDriver can spawn processes (check sandbox provider quota/health).
- Confirm the authPath option points at the real Codex auth.json location inside the image (default ~/.codex/auth.json).
- Inspect the non-secret progress lines (log callback) to see how far the run got before the failure.
Defensive patterns
Strategy: retry
Validate before calling
// The runner hides the original error by design, so pre-flight the driver instead.
async function canSpawn(driver: SandboxLoginDriver): Promise<boolean> {
try {
const r = await driver.execStreaming("true", () => {});
return r.exitCode === 0;
} catch { return false; }
} Try / catch
let attempt = 0;
let result: DeviceLoginResult;
while (true) {
try {
result = await runDeviceLogin(opts);
break;
} catch (e) {
if (e instanceof Error && /device login failed: the sandbox login command errored/.test(e.message) && attempt++ < 1) continue;
throw e;
}
}
// then inspect result.outcome for failure/timeout/cancelled distinctly Prevention
- Pre-flight the sandbox (spawn a no-op) before invoking the login command.
- Confirm the authPath exists in the image before the run starts.
- Keep the driver non-persistent so a bad sandbox is discarded, not reused.
- Surface the fixed log lines to the operator since the error itself is non-descriptive.
When it happens
Trigger: driver.execStreaming rejects (sandbox spawn failed, sandbox died mid-stream, network to sandbox dropped), or driver.readFile rejects (authPath missing/unreadable after a non-zero-exit was already handled), while running the device-login flow.
Common situations: Daytona sandbox quota exhausted or sandbox image unavailable; the auth.json path configured does not exist in the image; transient sandbox network failure during the login window; sandbox was deleted out from under the run.
Related errors
- post-upload command cwd is not a confined absolute POSIX pat
- post-upload command cwd escapes the operation's target root:
- networkAllowlist[${index}] must use an exact hostname; wildc
- sync operation ${label} path is not a confined absolute path
- sync operation ${label} path escapes its confinement root: $
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/a2442f7ed9656f3c.
Report an issue: GitHub.