paperclipai/paperclip · error

Invalid decision filters

Error message

Invalid decision filters

What it means

400 from the decision list routes. Generic validation-guard sentinel: fires when query filters for listing decisions (date range, kind, status etc.) fail schema parsing, so the handler rejects the request before querying.

Source

Thrown at server/src/routes/decisions.ts:151

        additionalTargetSnapshots: targetSnapshots,
      });
      res.status(201).json(created);
    },
  );
  router.post("/companies/:companyId/decisions", validate(createSchema), async (req, res) => {
    const companyId = req.params.companyId as string; assertCompanyAccess(req, companyId);
    const agent = agentContext(req); if (!agent) { res.status(403).json({ error: "Agent run context required" }); return; }
    res.status(201).json(await svc.create({ companyId, actor: req.actor, ...agent, ...req.body }));
  });
  router.post("/companies/:companyId/decision-bundles", validate(bundleSchema), async (req, res) => {
    const companyId = req.params.companyId as string; assertCompanyAccess(req, companyId);
    const agent = agentContext(req); if (!agent) { res.status(403).json({ error: "Agent run context required" }); return; }
    res.status(201).json(await svc.createBundle({ companyId, actor: req.actor, ...agent, ...req.body }));
  });
  router.get("/companies/:companyId/decisions", async (req, res) => {
    const companyId = req.params.companyId as string; assertBoard(req); assertCompanyAccess(req, companyId);
    const query = z.object({ status: z.enum(["open", "decided", "expired", "cancelled"]).optional(), bundleId: z.string().guid().optional(), targetIssueId: z.string().guid().optional(), originAgentId: z.string().guid().optional(), limit: z.coerce.number().int().positive().max(100).optional() }).safeParse(req.query);
    if (!query.success) { res.status(400).json({ error: "Invalid decision filters", details: query.error.flatten() }); return; }
    res.json(await svc.list(companyId, query.data));
  });
  /**
   * Gardener telemetry contract:
   * { groupBy: "ruleKey", filters: { originAgentId: string|null, since: ISO-8601|null },
   *   totals: { proposed, accepted, rejected, expired },
   *   groups: [{ ruleKey: string|null, proposed, accepted, rejected, expired,
   *     chosenOptions: [{ optionId, count }] }] }
   * Accepted means a non-dismissed decided outcome; rejected means an explicit dismiss;
   * chosenOptions counts accepted outcomes only; expired is separate, and cancelled
   * decisions contribute only to proposed.
   */
  router.get("/companies/:companyId/decisions/stats", async (req, res) => {
    const companyId = req.params.companyId as string; assertBoardOrAgent(req); assertCompanyAccess(req, companyId);
    const query = statsQuerySchema.safeParse(req.query);
    if (!query.success) { res.status(400).json({ error: "Invalid decision stats filters", details: query.error.flatten() }); return; }
    if (req.actor.type === "agent" && query.data.originAgentId && query.data.originAgentId !== req.actor.agentId) {
      res.status(403).json({ error: "Agents may only read their own decision stats" }); return;

View on GitHub (pinned to a7e689b3c3)

Solutions

  1. Fix the offending parameter to satisfy the constraint stated in the error message (type, range, or allowed values), then retry.
  2. Refer to the route's request validation in the named file and the shared validators for the accepted format.
Defensive patterns

Strategy: try-catch

When it happens

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

Common situations: See trigger scenarios.


AI-assisted analysis of paperclipai/paperclip@a7e689b3c3 (2026-08-21). Data as JSON: /api/errors/5c823160f304897f. Report an issue: GitHub.