paperclipai/paperclip · error
Runtime service control is outside this actor's authorizatio
Error message
Runtime service control is outside this actor's authorization boundary
What it means
HTTP 403 sent by assertRuntimeManageAllowed in the projects router when the access-control layer denies the actor's 'runtime:manage' action on the project's company. The route guards runtime service control (start/stop/restart style commands) behind a per-company authorization decision; the actor is authenticated but not authorized for this operation.
Source
Thrown at server/src/routes/projects.ts:151
async function assertProjectReadAllowed(req: Request, res: Response, project: { id: string; companyId: string }) {
const decision = await access.decide({
actor: req.actor,
action: "project:read",
resource: { type: "project", companyId: project.companyId, projectId: project.id },
});
if (decision.allowed) return true;
res.status(403).json({ error: "Project is outside this actor's authorization boundary" });
return false;
}
async function assertRuntimeManageAllowed(req: Request, res: Response, companyId: string) {
const decision = await access.decide({
actor: req.actor,
action: "runtime:manage",
resource: { type: "company", companyId },
});
if (decision.allowed) return true;
res.status(403).json({ error: "Runtime service control is outside this actor's authorization boundary" });
return false;
}
async function filterProjectsForActor<T extends { id: string; companyId: string }>(req: Request, rows: T[]) {
const decisions = await Promise.all(rows.map((project) =>
access.decide({
actor: req.actor,
action: "project:read",
resource: { type: "project", companyId: project.companyId, projectId: project.id },
})
));
return rows.filter((_, index) => decisions[index]?.allowed);
}
router.param("id", async (req, _res, next, rawId) => {
try {
req.params.id = await normalizeProjectReference(req, rawId);
next();View on GitHub (pinned to 01ad858492)
Solutions
- Grant the actor (role/policy) the runtime:manage permission for the project's company in the access-control configuration.
- Retry the call as a user/agent key that has runtime management rights on that company.
- If an agent key must manage runtimes, re-scope the request to the actor's own company or route it through a board-authorized service.
- Verify req.actor is correctly resolved (auth middleware loaded, correct company context) — a misattributed actor denies otherwise-valid calls.
Example fix
// before curl -H "Authorization: Bearer $AGENT_KEY" /api/projects/p1/workspaces/w1/runtime/restart // 403 Runtime service control is outside this actor's authorization boundary // after curl -H "Authorization: Bearer $BOARD_ADMIN_KEY" /api/projects/p1/workspaces/w1/runtime/restart
Defensive patterns
Strategy: try-catch
Validate before calling
// client-side pre-check
if (!actor.permissions?.includes('runtime:manage')) throw new Error('actor cannot manage runtime for this company'); Type guard
function canManageRuntime(actor) {
return typeof actor === 'object' && actor !== null && Array.isArray(actor.permissions) && actor.permissions.includes('runtime:manage');
} Try / catch
try {
const res = await fetch(url, { method: 'POST', headers });
if (res.status === 403) throw new AuthzError('runtime manage denied for this actor/company');
return await res.json();
} catch (e) {
if (e instanceof AuthzError) { notifyAdminToGrantPermission(); return null; }
throw e;
} Prevention
- Check the actor's runtime:manage grant before issuing runtime commands.
- Keep agent API keys scoped to their own company only.
- Re-check permissions after role changes on the board.
- Fall back to a board-authorized service account for runtime operations.
When it happens
Trigger: POST/PUT to a project workspace runtime command endpoint (e.g. /projects/:id/workspaces/:workspaceId/runtime/...) where access.decide({action:'runtime:manage'}) returns allowed:false for req.actor — e.g. an agent API key or a non-admin board user issuing runtime commands on a company they can only read.
Common situations: Agent bearer keys trying to restart a workspace runtime; board users with view-only role; actor from a different company than the project; missing runtime:manage grant after role changes.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- Run telemetry is outside this actor's authorization boundary
- trustPreset.detail
- Plugin UI is not available (status: ${plugin.status})
- Access denied
- DUPLEX_CHANNEL_CAPABILITY_DENIED
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/243ea6ead733b691.
Report an issue: GitHub.