paperclipai/paperclip · error

Only CEO can manage permissions

Error message

Only CEO can manage permissions

What it means

PATCH /agents/:id/permissions requires CEO role; the actor (after checks) is not the company CEO. Permission management is restricted to the CEO principal, so the route refuses with this message.

Solutions

  1. Perform permission changes as the CEO agent, or ask the CEO to make the change.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at server/src/routes/agents.ts:3473 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-08-18). Data as JSON: /api/errors/05f4139f2050b518. Report an issue: GitHub.

Appendix: source

Thrown at server/src/routes/agents.ts:4257

    const revisions = await svc.listConfigRevisions(id);
    res.json(revisions.map((revision) => redactConfigRevision(revision)));
  });

  router.get("/agents/:id/config-revisions/:revisionId", async (req, res) => {
    const id = req.params.id as string;
    const revisionId = req.params.revisionId as string;
    const agent = await svc.getById(id);
    if (!agent) {
      res.status(404).json({ error: "Agent not found" });
      return;
    }
    await assertCanReadConfigurations(req, agent.companyId);
    const revision = await svc.getConfigRevision(id, revisionId);
    if (!revision) {
      res.status(404).json({ error: "Revision not found" });
      return;
    }
    res.json(redactConfigRevision(revision));
  });

  router.post("/agents/:id/config-revisions/:revisionId/rollback", async (req, res) => {
    const id = req.params.id as string;
    const revisionId = req.params.revisionId as string;
    const existing = await getAccessibleResource(req, res, svc.getById(id), "Agent not found");
    if (!existing) return;
    await assertCanUpdateAgent(req, existing);

    const revision = await svc.getConfigRevision(id, revisionId);
    if (!revision) {
      res.status(404).json({ error: "Revision not found" });
      return;
    }
    const rollbackConfig = asRecord(revision.afterConfig);
    if (!rollbackConfig) {
      throw unprocessable("Invalid revision snapshot");
    }

View on GitHub (pinned to 3f1d897a7c)