paperclipai/paperclip · error · Error

Request failed: ${response.status}

Error message

Request failed: ${response.status}

What it means

Generic fallback thrown by the internal requestJson() helper in cli/src/client/board-auth.ts when an HTTP response is non-OK (not 2xx) AND the response body is missing, unparseable, or has no string-shaped `error` field. The literal status code is interpolated so the caller sees what the server returned. This helper backs the CLI board-auth flow (create-challenge, poll, /me, revoke), so the failure surfaces during CLI login/token-refresh/revoke, not during normal agent API calls.

Source

Thrown at cli/src/client/board-auth.ts:171

  if (init?.body !== undefined && !headers.has("content-type")) {
    headers.set("content-type", "application/json");
  }
  if (!headers.has("accept")) {
    headers.set("accept", "application/json");
  }

  const response = await fetch(url, {
    ...init,
    headers,
  });

  if (!response.ok) {
    const body = await response.json().catch(() => null);
    const message =
      body && typeof body === "object" && typeof (body as { error?: unknown }).error === "string"
        ? (body as { error: string }).error
        : `Request failed: ${response.status}`;
    throw new Error(message);
  }

  return response.json() as Promise<T>;
}

export async function openUrl(url: string): Promise<boolean> {
  const { command, args } =
    process.platform === "darwin"
      ? { command: "open", args: [url] }
      : process.platform === "win32"
        ? { command: "cmd", args: ["/c", "start", "", url] }
        : { command: "xdg-open", args: [url] };

  return new Promise<boolean>((resolve) => {
    let child: ChildProcess;
    try {
      child = spawn(command, args, { detached: true, stdio: "ignore" });
    } catch {

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Re-run with the correct API base: `paperclipai login --api-base https://your-paperclip.example.com` (no trailing path).
  2. Check the server is up and the cli-auth routes exist: `curl -i <apiBase>/api/health`.
  3. If a proxy is in front, confirm it passes JSON bodies through and does not rewrite 4xx/5xx into HTML pages.
  4. Retry the login; a transient 5xx during deploy resolves once the server is healthy.

Example fix

// before
paperclipai login --api-base https://corp.example.com/paperclip/api
// (HTML 404 page → "Request failed: 404")

// after — point at the API root, no /api suffix
paperclipai login --api-base https://corp.example.com
Defensive patterns

Strategy: try-catch

Validate before calling

// Before calling loginBoardCli / requestJson-style helpers, sanity-check the apiBase.
function assertApiBase(apiBase: string): void {
  const u = new URL(apiBase); // throws on garbage
  if (!u.protocol.startsWith('http')) throw new Error(`apiBase must be http(s): ${apiBase}`);
  if (/[?]#/.test(u.href)) throw new Error(`apiBase must not include query/fragment: ${apiBase}`);
}

Type guard

function isApiErrorBody(body: unknown): body is { error: string } {
  return typeof body === 'object' && body !== null &&
    typeof (body as any).error === 'string';
}

Try / catch

try {
  await loginBoardCli({ apiBase, ... });
} catch (err) {
  const msg = err instanceof Error ? err.message : String(err);
  if (/^Request failed: \d+$/.test(msg)) {
    const status = Number(msg.slice('Request failed: '.length));
    console.error(`Board auth HTTP ${status} from ${apiBase}; check server health and apiBase.`);
  }
  throw err;
}

Prevention

When it happens

Trigger: A board-auth endpoint returns a non-2xx (e.g. 401 on /api/cli-auth/me with a bad/revoked boardApiToken, 404 on a challenge pollPath that does not exist, 500 from the server, or a network proxy returning 502/503) and the body is either empty, not JSON, or JSON without `{ error: string }`. Also triggered if the apiBase is wrong (points at a non-Paperclip host returning HTML, so `.json().catch(()=>null)` yields null).

Common situations: Wrong --api-base (typo, trailing path, pointing at the UI host instead of the API host), server down or restarting during `paperclipai login`, reverse proxy returning an HTML error page (status body not JSON), token revoked between challenge approval and the /api/cli-auth/me call, or a version mismatch where the server's cli-auth routes changed.

Related errors


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