{"record":{"id":"93822ed375237ecd","repo":"paperclipai/paperclip","slug":"invalid-decision-stats-filters","errorCode":null,"errorMessage":"Invalid decision stats filters","messagePattern":"Invalid decision stats filters","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"server/src/routes/decisions.ts","lineNumber":167,"sourceCode":"    const companyId = req.params.companyId as string; assertBoard(req); assertCompanyAccess(req, companyId);\n    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);\n    if (!query.success) { res.status(400).json({ error: \"Invalid decision filters\", details: query.error.flatten() }); return; }\n    res.json(await svc.list(companyId, query.data));\n  });\n  /**\n   * Gardener telemetry contract:\n   * { groupBy: \"ruleKey\", filters: { originAgentId: string|null, since: ISO-8601|null },\n   *   totals: { proposed, accepted, rejected, expired },\n   *   groups: [{ ruleKey: string|null, proposed, accepted, rejected, expired,\n   *     chosenOptions: [{ optionId, count }] }] }\n   * Accepted means a non-dismissed decided outcome; rejected means an explicit dismiss;\n   * chosenOptions counts accepted outcomes only; expired is separate, and cancelled\n   * decisions contribute only to proposed.\n   */\n  router.get(\"/companies/:companyId/decisions/stats\", async (req, res) => {\n    const companyId = req.params.companyId as string; assertBoardOrAgent(req); assertCompanyAccess(req, companyId);\n    const query = statsQuerySchema.safeParse(req.query);\n    if (!query.success) { res.status(400).json({ error: \"Invalid decision stats filters\", details: query.error.flatten() }); return; }\n    if (req.actor.type === \"agent\" && query.data.originAgentId && query.data.originAgentId !== req.actor.agentId) {\n      res.status(403).json({ error: \"Agents may only read their own decision stats\" }); return;\n    }\n    const originAgentId = req.actor.type === \"agent\" ? req.actor.agentId : query.data.originAgentId;\n    res.json(await svc.stats(companyId, { originAgentId, since: query.data.since }));\n  });\n  router.get(\"/decisions/:id\", async (req, res) => {\n    assertBoardOrAgent(req);\n    const decision = await getAccessibleResource(req, res, svc.get(req.params.id as string), \"Decision not found\");\n    if (!decision) return;\n    if (req.actor.type === \"agent\" && req.actor.agentId !== decision.originAgentId) { res.status(403).json({ error: \"Only the origin agent may read this decision\" }); return; }\n    res.json(await svc.outcome(decision.id));\n  });\n  router.post(\"/decisions/:id/decide\", validate(decideSchema), async (req, res) => {\n    const userId = boardUserId(req);\n    const decision = await getAccessibleResource(req, res, svc.get(req.params.id as string), \"Decision not found\");\n    if (!decision) return;\n    res.json(await svc.decide({ id: decision.id, decidedByUserId: userId, userActor: req.actor, ...req.body }));","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/paperclipai/paperclip/blob/a7e689b3c35347b529cb9f54c9b9a8575a3dcab6/server/src/routes/decisions.ts#L149-L185","documentation":"Query-schema guard on the decisions list route: the status/bundleId/targetIssueId/originAgentId/limit query failed its Zod parse (bad enum, non-UUID, or out-of-range limit), so the list request is rejected with 400 and the flattened issues.","triggerScenarios":"Thrown at server/src/routes/decisions.ts:167 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","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."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"a7e689b3c35347b529cb9f54c9b9a8575a3dcab6","analyzedAt":"2026-08-18T22:49:45.177Z","contentChangedAt":"2026-08-18T22:49:45.177Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}