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
- Check CLI and server versions are aligned (npm view / release notes for /api/agents/:id/keys).
- Retry — a transient empty response can occur during deploys.
- Inspect the server logs for the /keys request to see what body it returned.
- 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
- Keep CLI and server versions in sync; the /keys contract changes between releases.
- Retry once on empty responses during deploys.
- Have a board-UI fallback for key creation when the API path misbehaves.
- Log the server response shape when this fires so the mismatch is diagnosable.
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
- Refusing to delete without --yes
- Agent not found: ${agentRef}
- --payload must be a JSON object
- Agent authentication failed
- Agent not found: ${agentRef}
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/6a10e00689d95ba1.
Report an issue: GitHub.