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

  1. Retry the device login once — sandbox spawn failures are often transient.
  2. Verify the sandbox image is reachable and the SandboxLoginDriver can spawn processes (check sandbox provider quota/health).
  3. Confirm the authPath option points at the real Codex auth.json location inside the image (default ~/.codex/auth.json).
  4. 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

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


AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12). Data as JSON: /api/errors/a2442f7ed9656f3c. Report an issue: GitHub.