{"record":{"id":"38336dae0cec2619","repo":"paperclipai/paperclip","slug":"formal-approval-required","errorCode":"formal_approval_required","errorMessage":"Tool action request requires formal board approval before execution","messagePattern":"Tool action request requires formal board approval before execution","errorType":"http","errorClass":"ToolGatewayHttpError","httpStatus":409,"severity":"error","filePath":"server/src/services/tool-gateway.ts","lineNumber":5450,"sourceCode":"    const settled = await db.transaction(async (tx) => {\n      // Lock in the same invocation -> request order used by the normal\n      // execution settlement path. The claim timestamp is the ownership token:\n      // a consumer that merely read an approved row cannot settle another\n      // consumer's claim, and a pre-dispatch failure cannot overwrite a call\n      // that has already entered provider execution or completed successfully.\n      const [invocation] = await tx\n        .select({ status: toolInvocations.status })\n        .from(toolInvocations)\n        .where(eq(toolInvocations.id, input.invocationId))\n        .for(\"update\")\n        .limit(1);\n      if (invocation?.status !== input.expectedInvocationStatus) return false;\n\n      const [actionRequest] = await tx\n        .select({ status: toolActionRequests.status, updatedAt: toolActionRequests.updatedAt })\n        .from(toolActionRequests)\n        .where(eq(toolActionRequests.id, input.actionRequestId))\n        .for(\"update\")\n        .limit(1);\n      if (\n        actionRequest?.status !== \"executing\"\n        || actionRequest.updatedAt.getTime() !== input.claimUpdatedAt.getTime()\n      ) {\n        return false;\n      }\n\n      await tx.update(toolInvocations).set({\n        status: \"failed\",\n        idempotencyKey: null,\n        errorCode: reasonCode,\n        errorMessage: message,\n        completedAt: now,\n        updatedAt: now,\n      }).where(and(\n        eq(toolInvocations.id, input.invocationId),\n        eq(toolInvocations.status, input.expectedInvocationStatus),","sourceCodeStart":5432,"sourceCodeEnd":5468,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/server/src/services/tool-gateway.ts#L5432-L5468","documentation":"Governance guard during approval resolution: the action request references a formal approvals row that is missing or not in approved status. The 409 formal_approval_required blocks execution until the board formally approves the linked approval record, since this action was configured to require formal approval.","triggerScenarios":"Thrown at server/src/services/tool-gateway.ts:5282 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["This action requires formal board approval; route it through the board approval flow instead of executing directly."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-08-18T22:49:45.177Z","contentChangedAt":"2026-08-18T22:49:45.177Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}