paperclipai/paperclip · error · Error
Creating companies requires board/instance-admin authenticat
Error message
Creating companies requires board/instance-admin authentication. Agent API keys are scoped to one company; use `paperclipai company list --json` or `paperclipai company current --json` to select the scoped company, or rerun create with a board token/login.
What it means
Thrown by createCompanyForContext() when the POST /api/companies fails with a 403 whose message indicates 'board access required' or 'instance admin'. Creating companies is a board/instance-admin privilege; agent API keys are scoped to a single existing company and cannot create new ones. The helper detects both 403 variants and re-throws a user-facing explanation.
Source
Thrown at cli/src/commands/client/company.ts:2024
} catch (error) {
if (!isBoardAccessRequiredError(error)) {
throw error;
}
}
const companyId = await resolveCurrentCompanyId(ctx);
const scopedCompany = await ctx.api.get<Company>(apiPath`/api/companies/${companyId}`);
return scopedCompany ? [scopedCompany] : [];
}
async function createCompanyForContext(ctx: {
api: { post<T>(path: string, body?: unknown): Promise<T | null> };
}, payload: unknown): Promise<unknown> {
try {
return await ctx.api.post("/api/companies", payload);
} catch (error) {
if (isBoardAccessRequiredError(error) || isInstanceAdminRequiredError(error)) {
throw new Error(
"Creating companies requires board/instance-admin authentication. Agent API keys are scoped to one company; use `paperclipai company list --json` or `paperclipai company current --json` to select the scoped company, or rerun create with a board token/login.",
);
}
throw error;
}
}
async function resolveCurrentCompanyId(ctx: { companyId?: string; api: { get<T>(path: string): Promise<T | null> } }): Promise<string> {
const fromContext = ctx.companyId?.trim();
if (fromContext) return fromContext;
let agent: AgentMeResponse | null = null;
try {
agent = await ctx.api.get<AgentMeResponse>("/api/agents/me");
} catch (error) {
if (error instanceof ApiRequestError && (error.status === 401 || error.status === 403)) {
throw new Error(
"Current company is not available. Pass --company-id, set PAPERCLIP_COMPANY_ID, set a context profile companyId, or authenticate with an agent API key.",View on GitHub (pinned to 67001ec6eb)
Solutions
- Authenticate as board: run `paperclipai connect` and choose the board persona, or set a board API key via PAPERCLIP_API_KEY.
- Provision the company out-of-band (admin UI / API directly) and then have agents reference it.
- Confirm the token's scope with `paperclipai context current`.
Example fix
# before export PAPERCLIP_API_KEY=$AGENT_KEY paperclipai company create --name newco # after export PAPERCLIP_API_KEY=$BOARD_KEY paperclipai company create --name newco
Defensive patterns
Strategy: try-catch
Validate before calling
// Guard company create behind a board-token check before calling the API.
function requireBoardPersona(profile: { persona?: string }): void {
if (profile.persona !== "board") {
throw new Error("Company create requires a board/instance-admin token; run 'paperclipai connect' as board.");
}
} Type guard
import { ApiRequestError } from "../../client/http.js";
function isBoardOrInstanceAdmin403(err: unknown): boolean {
if (!(err instanceof ApiRequestError) || err.status !== 403) return false;
const m = err.message.toLowerCase();
return m.includes("board access required") || m.includes("instance admin");
} Try / catch
try {
return await ctx.api.post("/api/companies", payload);
} catch (err) {
if (isBoardOrInstanceAdmin403(err)) {
throw new Error("Switch to a board/instance-admin token to create companies.");
}
throw err;
} Prevention
- Keep a dedicated board token for provisioning workflows; separate from agent keys.
- Provision companies via admin tooling, then hand agents a company-scoped key.
- Assert persona === 'board' in wrappers before calling create.
When it happens
Trigger: Running `paperclipai company create` with an agent API key; a token that is company-scoped rather than board-scoped; a context profile configured with persona 'agent'.
Common situations: Agent automation attempting to bootstrap a new company; CI using an agent key for provisioning; the default context was set up via agent auth instead of board auth.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Board access is required to resolve companies across the ins
- Request failed: ${response.status}
- CLI auth challenge was cancelled.
- CLI auth challenge expired before approval.
- Failed to parse JSON at ${filePath}: ${err instanceof Error
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/4054e1c9b44db286.
Report an issue: GitHub.