paperclipai/paperclip · error · Error
Failed to create agent API key
Error message
Failed to create agent API key
What it means
Thrown by the `agent create` action in token.ts when ctx.api.post to /api/agents/{id}/keys returns a falsy value (null/undefined). The POST must return a CreatedAgentKey object; an empty 2xx body, a proxy that stripped the body, or an API client that resolves null on parse failure trips this guard.
Source
Thrown at cli/src/commands/client/token.ts:78
export function registerTokenCommands(program: Command): void {
const token = program.command("token").description("Manage Paperclip API tokens");
const agent = token.command("agent").description("Manage agent API keys");
addCommonClientOptions(
agent
.command("create")
.description("Create an agent API key")
.requiredOption("-C, --company-id <id>", "Company ID")
.requiredOption("--agent <agent>", "Agent ID, shortname, or unambiguous name")
.option("--name <name>", "API key label", "cli-agent")
.action(async (opts: AgentTokenOptions) => {
try {
const ctx = resolveCommandContext(opts, { requireCompany: true });
const agentRow = await resolveAgent(ctx.api, ctx.companyId ?? "", opts.agent ?? "");
const payload = createAgentKeySchema.parse({ name: opts.name });
const key = await ctx.api.post<CreatedAgentKey>(apiPath`/api/agents/${agentRow.id}/keys`, payload);
if (!key) throw new Error("Failed to create agent API key");
printOutput(
{
agentId: agentRow.id,
agentName: agentRow.name,
companyId: agentRow.companyId,
key,
},
{ json: ctx.json },
);
} catch (err) {
handleCommandError(err);
}
}),
{ includeCompany: false },
);
addCommonClientOptions(
agentView on GitHub (pinned to 67001ec6eb)
Solutions
- Verify the server is the expected Paperclip version for this CLI: compare /api/health and the CLI version.
- Hit the endpoint directly with curl -X POST /api/agents/{id}/keys to inspect the raw response body.
- Check API_BASE / base URL resolution so the post targets the Paperclip API and not a gateway returning empty.
- Inspect CLI verbose/debug logs for the raw response status and body.
Example fix
// before: server returns {} or empty 2xx
// fix server handler to return the created key object
res.status(201).json({ id, key, name, agentId }); Defensive patterns
Strategy: try-catch
Type guard
function isCreatedAgentKey(value: unknown): value is CreatedAgentKey {
return !!value && typeof value === "object" && "key" in value && typeof (value as any).key === "string";
} Try / catch
try {
const key = await ctx.api.post<CreatedAgentKey>(path, payload);
if (!isCreatedAgentKey(key)) throw new Error("Server returned no key body");
// use key
} catch (err) {
handleCommandError(err);
} Prevention
- Keep CLI and server versions aligned so the response shape matches.
- Verify the API base URL points at Paperclip, not a proxy returning empty.
- Hit POST /api/agents/{id}/keys with curl first to confirm a non-empty body.
When it happens
Trigger: Calling `paperclipai ... token agent create --company-id X --agent Y` where the server returns 200/201 with an empty body, or the API client's post helper resolves null on a malformed JSON response.
Common situations: Misconfigured API base URL hitting a different service, a reverse proxy that rewrites the response, an outdated CLI talking to an API version that changed the key-creation response shape, or a network layer returning null on JSON parse failure.
Related errors
- Failed to create board API key
- Import transfer declaration returned no data.
- No update status returned for skill ${skill.key}.
- No audit result returned for skill ${skill.key}.
- Approval request failed.
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/2682e10c67c0424c.
Report an issue: GitHub.