paperclipai/paperclip · error · Error

Failed to create API key

Error message

Failed to create API key

What it means

Thrown by the local-cli action when POST /api/agents/{id}/keys returned a falsy value (the client typed the response as CreatedAgentKey but the server returned null/undefined/empty). The agent lookup already succeeded ([7] would have fired otherwise), so this is a key-creation endpoint returning an unexpected empty body.

Source

Thrown at cli/src/commands/client/agent.ts:791

        "--no-install-skills",
        "Skip installing Paperclip skills into ~/.codex/skills and ~/.claude/skills",
      )
      .action(async (agentRef: string, opts: AgentLocalCliOptions) => {
        try {
          const ctx = resolveCommandContext(opts, { requireCompany: true });
          const query = new URLSearchParams({ companyId: ctx.companyId ?? "" });
          const agentRow = await ctx.api.get<Agent>(
            `${apiPath`/api/agents/${agentRef}`}?${query.toString()}`,
          );
          if (!agentRow) {
            throw new Error(`Agent not found: ${agentRef}`);
          }

          const now = new Date().toISOString().replaceAll(":", "-");
          const keyName = opts.keyName?.trim() ? opts.keyName.trim() : `local-cli-${now}`;
          const key = await ctx.api.post<CreatedAgentKey>(apiPath`/api/agents/${agentRow.id}/keys`, { name: keyName });
          if (!key) {
            throw new Error("Failed to create API key");
          }

          const installSummaries: SkillsInstallSummary[] = [];
          if (opts.installSkills !== false) {
            const skillsDir = await resolvePaperclipSkillsDir(__moduleDir, [path.resolve(process.cwd(), "skills")]);
            if (!skillsDir) {
              throw new Error(
                "Could not locate local Paperclip skills directory. Expected ./skills in the repo checkout.",
              );
            }

            installSummaries.push(
              await installSkillsForTarget(skillsDir, codexSkillsHome(), "codex"),
              await installSkillsForTarget(skillsDir, claudeSkillsHome(), "claude"),
            );
          }

          const exportsText = buildAgentEnvExports({

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Check CLI and server versions are aligned (npm view / release notes for /api/agents/:id/keys).
  2. Retry — a transient empty response can occur during deploys.
  3. Inspect the server logs for the /keys request to see what body it returned.
  4. If persistent, report the server response shape as a bug; fall back to creating the key via the board UI.
Defensive patterns

Strategy: try-catch

Type guard

function isCreatedKey(v: unknown): v is { key: string; name: string; id?: string } {
  return typeof v === 'object' && v !== null && typeof (v as any).key === 'string';
}

Try / catch

let key;
try { key = await api.post(`/api/agents/${agent.id}/keys`, { name: keyName }); }
catch (err) { /* network/HTTP errors */ throw err; }
if (!isCreatedKey(key)) {
  console.error('Server returned no key body from /keys — possible version mismatch. Create the key in the board UI.');
  process.exit(3);
}

Prevention

When it happens

Trigger: The agent exists but the key-creation route returned no body (e.g. 200 with empty JSON, or the client deserialized a 204/null). This typically indicates a server bug or a version mismatch where /keys changed shape, or the API client's response unwrapping returned undefined.

Common situations: Server version older/newer than the CLI expects for the /keys contract. A proxy stripping the response body. Rare server-side error swallowed into a 200 with null.

Related errors


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