{"record":{"id":"37756fcbf3cf43fc","repo":"paperclipai/paperclip","slug":"accessdecision-explanation","errorCode":null,"errorMessage":"accessDecision.explanation","messagePattern":"accessDecision\\.explanation","errorType":"http","errorClass":"ToolGatewayHttpError","httpStatus":null,"severity":"error","filePath":"server/src/services/tool-gateway.ts","lineNumber":5984,"sourceCode":"\n    let phase: ToolConnectionTestCallStatusPhase;\n    if (actionRequest.status === \"rejected\") {\n      phase = \"denied\";\n    } else if (actionRequest.status === \"cancelled\") {\n      phase = \"cancelled\";\n    } else if (actionRequest.status === \"expired\") {\n      phase = \"expired\";\n    } else if (actionRequest.status === \"approved\" || actionRequest.status === \"executed\") {\n      phase = invocationDone ? \"done\" : \"running\";\n    } else {\n      phase = \"waiting\";\n    }\n\n    // Recover a redacted, structured snapshot of the parameters for the\n    // \"Where\" row — the test-call response never echoes them back.\n    let parameters: Record<string, unknown> | null = null;\n    const signed = readSignedToolArgumentsPayload({\n      signedArguments: actionRequest.signedArguments,\n      invocationId: invocation.id,\n      toolName: invocation.toolName,\n      signingSecret: options.toolActionSigningSecret,\n    });\n    if (signed && signed.arguments && typeof signed.arguments === \"object\" && !Array.isArray(signed.arguments)) {\n      const redacted = validateToolContent({\n        value: signed.arguments,\n        direction: \"arguments\",\n        sensitiveMode: \"redact\",\n        promptInjectionMode: \"ignore\",\n      }).value;\n      if (redacted && typeof redacted === \"object\" && !Array.isArray(redacted)) {\n        parameters = redacted as Record<string, unknown>;\n      }\n    }\n\n    let result: unknown;\n    let error: ToolConnectionTestCallStatus[\"error\"];","sourceCodeStart":5966,"sourceCodeEnd":6002,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/server/src/services/tool-gateway.ts#L5966-L6002","documentation":"Not a literal throw message: this is the audit details block written on tool_gateway.call_denied, where the access policy decision is recorded. The referenced field is accessDecision.explanation — the policy engine's human-readable denial reason (which policy matched and why), persisted alongside decision, reasonCode, and matchedPolicyIds for each denied call.","triggerScenarios":"Thrown at server/src/services/tool-gateway.ts:5797 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Access was denied by policy; read the decision explanation for the specific reason and adjust the request (scope, tool, or arguments) accordingly."],"exampleFix":null,"handlingStrategy":"try-catch","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"}