paperclipai/paperclip · error · Error
Failed to create board API key
Error message
Failed to create board API key
What it means
Thrown by the `board create` action in token.ts when ctx.api.post to /api/board-api-keys returns a falsy value. Mirrors error 122 but for board-scope keys: the server must return a CreatedBoardKey object; an empty or unparseable body trips the guard.
Source
Thrown at cli/src/commands/client/token.ts:162
board
.command("create")
.description("Create a named board API key")
.option("-C, --company-id <id>", "Company ID used for audit context")
.option("--name <name>", "API key label", "cli-board")
.option("--expires-at <iso8601>", "Expiration timestamp")
.option("--ttl-days <days>", "Expiration in days from now")
.option("--never-expires", "Create a non-expiring key")
.action(async (opts: BoardTokenOptions) => {
try {
const ctx = resolveCommandContext(opts);
const expiresAt = resolveBoardKeyExpiresAt(opts);
const payload = createBoardApiKeySchema.parse({
name: opts.name,
requestedCompanyId: opts.companyId ?? ctx.companyId ?? null,
expiresAt,
});
const key = await ctx.api.post<CreatedBoardKey>("/api/board-api-keys", payload);
if (!key) throw new Error("Failed to create board API key");
printOutput({ key }, { json: ctx.json });
} catch (err) {
handleCommandError(err);
}
}),
{ includeCompany: false },
);
addCommonClientOptions(
board
.command("list")
.description("List board API keys for the current board user")
.action(async (opts: BaseClientOptions) => {
try {
const ctx = resolveCommandContext(opts);
const keys = (await ctx.api.get<BoardKeyRow[]>("/api/board-api-keys")) ?? [];
if (ctx.json) {
printOutput(keys, { json: true });View on GitHub (pinned to 67001ec6eb)
Solutions
- Confirm board-api-keys POST returns a non-empty JSON body via curl.
- Align CLI and server versions.
- Check the API base URL and auth header are correct.
- Enable CLI debug output to see the raw response.
Example fix
// before: board-api-keys POST returns '' or {}
// after: server returns the created key
res.status(201).json({ id, key, name, expiresAt }); Defensive patterns
Strategy: try-catch
Type guard
function isCreatedBoardKey(value: unknown): value is CreatedBoardKey {
return !!value && typeof value === "object" && "key" in value && typeof (value as any).key === "string";
} Try / catch
try {
const key = await ctx.api.post<CreatedBoardKey>("/api/board-api-keys", payload);
if (!isCreatedBoardKey(key)) throw new Error("Server returned no board key body");
} catch (err) {
handleCommandError(err);
} Prevention
- Align CLI and server versions.
- Confirm /api/board-api-keys returns a JSON body via curl.
- Check the API base URL and auth header.
When it happens
Trigger: Calling `paperclipai ... token board create ...` and the server returns an empty 2xx body, or the API client resolves null because the JSON did not match the expected shape.
Common situations: API/CLI version skew, a proxy stripping the response body, schema validator on the client rejecting the body and resolving null, or a misconfigured base URL.
Related errors
- Failed to create agent 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/a7cc91d4f5949656.
Report an issue: GitHub.