paperclipai/paperclip · error
companyId is required
Error message
companyId is required
What it means
HTTP 400 from the tool-gateway approve endpoint when neither body.companyId nor ?companyId= supplies a company id. The endpoint needs the company scope for the authorization check and the gateway call.
Source
Thrown at server/src/routes/tool-gateway.ts:592
approvedActionRequestId:
typeof body.approvedActionRequestId === "string" ? body.approvedActionRequestId : null,
idempotencyKey: typeof body.idempotencyKey === "string" ? body.idempotencyKey : null,
callerHeaders: callerHeaders(req),
});
res.json(result);
} catch (err) {
sendGatewayError(res, err);
}
});
router.post("/tool-gateway/action-requests/:id/approve", async (req, res) => {
try {
assertBoard(req);
const body = (req.body ?? {}) as { companyId?: string; rememberAction?: boolean };
if (body.rememberAction !== undefined && typeof body.rememberAction !== "boolean") { res.status(400).json({ error: "rememberAction must be a boolean" }); return; }
const companyId = body.companyId ?? (typeof req.query.companyId === "string" ? req.query.companyId : null);
if (!companyId) {
res.status(400).json({ error: "companyId is required" });
return;
}
assertBoardMutationAccess(req, companyId);
const actor = getActorInfo(req);
const actionRequest = await toolGateway.approveActionRequest({
companyId,
actionRequestId: req.params.id,
rememberAction: body.rememberAction,
actor: {
agentId: actor.agentId,
userId: req.actor.type === "board" ? req.actor.userId : null,
},
});
res.json(actionRequest);
} catch (err) {
sendGatewayError(res, err);
}
});View on GitHub (pinned to 01ad858492)
Solutions
- Include companyId in the JSON body: {"companyId": "..."}.
- Or append ?companyId=... to the request URL.
- Ensure the calling UI/SDK passes the currently selected company context.
- Check that the body is sent with application/json so req.body parses (an unparsed body makes body.companyId undefined).
Example fix
// before
POST /api/tool-gateway/action-requests/ar1/approve {}
// 400 companyId is required
// after
POST /api/tool-gateway/action-requests/ar1/approve {"companyId":"c1"} Defensive patterns
Strategy: validation
Validate before calling
if (!companyId || typeof companyId !== 'string') throw new Error('companyId is required to approve a tool-gateway action request'); Type guard
const hasCompanyId = (b) => typeof b?.companyId === 'string' && b.companyId.length > 0;
Try / catch
try {
return await approveActionRequest({ actionRequestId, companyId });
} catch (e) {
if (e.status === 400 && /companyId/.test(e.body?.error ?? '')) {
throw new Error('configure the active company in the client before approving actions');
}
throw e;
} Prevention
- Thread the selected company through every tool-gateway call.
- Send companyId in the body, not just the query string, to avoid serialization gaps.
- Ensure requests use Content-Type: application/json so req.body parses.
- Centralize API calls in a client that injects companyId automatically.
When it happens
Trigger: POST /api/tool-gateway/action-requests/:id/approve with an empty body and no companyId query parameter — companyId resolves to null.
Common situations: Client relies on a company context header the route doesn't read; calling from scripts/tests without tenant context; multi-tenant UI forgetting to pass the selected company.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Invalid status '${String(rawStatus)}'. Must be one of: ${PLU
- "tool" is required and must be a string
- "runContext" is required and must be an object
- "runContext" must include agentId, runId, companyId, and pro
- invalid_provider
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/19ce1abefd345fc7.
Report an issue: GitHub.