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
- Fix the offending parameter to satisfy the constraint stated in the error message (type, range, or allowed values), then retry.
- 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.