paperclipai/paperclip · warning
"runContext" must include agentId, runId, companyId, and pro
Error message
"runContext" must include agentId, runId, companyId, and projectId
What it means
Returned as HTTP 400 by POST /api/plugins/tools/execute (server/src/routes/plugins.ts:1025) when runContext is an object but at least one of agentId, runId, companyId, projectId is falsy (missing, empty string, null). All four identify the execution scope checked afterwards by assertCompanyAccess and validateToolRunContextScope, so partial contexts are rejected up front.
Source
Thrown at server/src/routes/plugins.ts:1040
res.status(400).json({ error: "Request body is required" });
return;
}
const { tool, parameters, runContext } = body;
// Validate required fields
if (!tool || typeof tool !== "string") {
res.status(400).json({ error: '"tool" is required and must be a string' });
return;
}
if (!runContext || typeof runContext !== "object") {
res.status(400).json({ error: '"runContext" is required and must be an object' });
return;
}
if (!runContext.agentId || !runContext.runId || !runContext.companyId || !runContext.projectId) {
res.status(400).json({
error: '"runContext" must include agentId, runId, companyId, and projectId',
});
return;
}
assertCompanyAccess(req, runContext.companyId);
const scopeError = await validateToolRunContextScope(runContext);
if (scopeError) {
res.status(403).json({ error: scopeError });
return;
}
if (req.actor.type === "agent" && toolGatewayDeps) {
try {
const result = await toolGatewayDeps.toolGateway.executePluginTool({
actor: {
type: "agent",
agentId: req.actor.agentId,View on GitHub (pinned to a7e689b3c3)
Solutions
- Populate all four fields — create a run first if runId is missing, and select/derive companyId and projectId before executing
- Assert non-empty values client-side before sending (a quick every() over the four keys)
- Update older callers that predate the projectId requirement to thread project context through
Example fix
// before
const runContext = { agentId, runId, companyId };
// after
const runContext = { agentId, runId, companyId, projectId };
const required = ["agentId", "runId", "companyId", "projectId"] as const;
if (!required.every((k) => runContext[k])) {
throw new Error(`runContext missing: ${required.filter((k) => !runContext[k]).join(", ")}`);
} Defensive patterns
Strategy: validation
Validate before calling
const required = ["agentId", "runId", "companyId", "projectId"] as const;
const missing = required.filter((k) => !runContext[k]);
if (missing.length) {
throw new Error(`runContext missing required fields: ${missing.join(", ")}`);
}
await api.executePluginTool({ tool, parameters, runContext }); Type guard
type CompleteRunContext = { agentId: string; runId: string; companyId: string; projectId: string };
const isCompleteRunContext = (v: unknown): v is CompleteRunContext => {
const c = v as Record<string, unknown>;
return ["agentId", "runId", "companyId", "projectId"].every((k) => typeof c?.[k] === "string" && c[k] !== "");
}; Prevention
- Create the run and select the company/project before any tool execute call so all four ids exist
- Type the context as CompleteRunContext at the call boundary so missing fields fail to compile
When it happens
Trigger: runContext: {agentId, runId, companyId} without projectId (common after projectId was added to the contract); any of the four set to '' after trimming form input; contexts built from optional session fields that are undefined outside a run (e.g. invoking tools from a background job with no runId).
Common situations: Clients updated for three of the four ids; test harnesses reusing a stale context object; code paths executing tools outside an active run where runId was never created; company/project context not selected yet in the UI.
Related errors
- "tool" is required and must be a string
- "runContext" is required and must be an object
- Invalid status '${String(rawStatus)}'. Must be one of: ${PLU
- Request body is required
- Invalid file path
AI-assisted analysis of paperclipai/paperclip@a7e689b3c3 (2026-08-18).
Data as JSON: /api/errors/8ea6e41bb57bbd2b.
Report an issue: GitHub.