{"record":{"id":"19ce1abefd345fc7","repo":"paperclipai/paperclip","slug":"companyid-is-required","errorCode":null,"errorMessage":"companyId is required","messagePattern":"companyId is required","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"server/src/routes/tool-gateway.ts","lineNumber":592,"sourceCode":"        approvedActionRequestId:\n          typeof body.approvedActionRequestId === \"string\" ? body.approvedActionRequestId : null,\n        idempotencyKey: typeof body.idempotencyKey === \"string\" ? body.idempotencyKey : null,\n        callerHeaders: callerHeaders(req),\n      });\n      res.json(result);\n    } catch (err) {\n      sendGatewayError(res, err);\n    }\n  });\n\n  router.post(\"/tool-gateway/action-requests/:id/approve\", async (req, res) => {\n    try {\n      assertBoard(req);\n      const body = (req.body ?? {}) as { companyId?: string; rememberAction?: boolean };\n      if (body.rememberAction !== undefined && typeof body.rememberAction !== \"boolean\") { res.status(400).json({ error: \"rememberAction must be a boolean\" }); return; }\n      const companyId = body.companyId ?? (typeof req.query.companyId === \"string\" ? req.query.companyId : null);\n      if (!companyId) {\n        res.status(400).json({ error: \"companyId is required\" });\n        return;\n      }\n      assertBoardMutationAccess(req, companyId);\n      const actor = getActorInfo(req);\n      const actionRequest = await toolGateway.approveActionRequest({\n        companyId,\n        actionRequestId: req.params.id,\n        rememberAction: body.rememberAction,\n        actor: {\n          agentId: actor.agentId,\n          userId: req.actor.type === \"board\" ? req.actor.userId : null,\n        },\n      });\n      res.json(actionRequest);\n    } catch (err) {\n      sendGatewayError(res, err);\n    }\n  });","sourceCodeStart":574,"sourceCodeEnd":610,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/server/src/routes/tool-gateway.ts#L574-L610","documentation":"HTTP 400 from the tool-gateway approve endpoint when neither body.companyId nor ?companyId= supplies a company id. The endpoint needs the company scope for the authorization check and the gateway call.","triggerScenarios":"POST /api/tool-gateway/action-requests/:id/approve with an empty body and no companyId query parameter — companyId resolves to null.","commonSituations":"Client relies on a company context header the route doesn't read; calling from scripts/tests without tenant context; multi-tenant UI forgetting to pass the selected company.","solutions":["Include companyId in the JSON body: {\"companyId\": \"...\"}.","Or append ?companyId=... to the request URL.","Ensure the calling UI/SDK passes the currently selected company context.","Check that the body is sent with application/json so req.body parses (an unparsed body makes body.companyId undefined)."],"exampleFix":"// before\nPOST /api/tool-gateway/action-requests/ar1/approve  {}\n// 400 companyId is required\n// after\nPOST /api/tool-gateway/action-requests/ar1/approve  {\"companyId\":\"c1\"}","handlingStrategy":"validation","validationCode":"if (!companyId || typeof companyId !== 'string') throw new Error('companyId is required to approve a tool-gateway action request');","typeGuard":"const hasCompanyId = (b) => typeof b?.companyId === 'string' && b.companyId.length > 0;","tryCatchPattern":"try {\n  return await approveActionRequest({ actionRequestId, companyId });\n} catch (e) {\n  if (e.status === 400 && /companyId/.test(e.body?.error ?? '')) {\n    throw new Error('configure the active company in the client before approving actions');\n  }\n  throw e;\n}","preventionTips":["Thread the selected company through every tool-gateway call.","Send companyId in the body, not just the query string, to avoid serialization gaps.","Ensure requests use Content-Type: application/json so req.body parses.","Centralize API calls in a client that injects companyId automatically."],"tags":["validation","http-400","missing-parameter","multi-tenant"],"backgroundTag":"missing-required-argument","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}