{"record":{"id":"3d2c841712b88063","repo":"paperclipai/paperclip","slug":"paperclip-runner-tool-not-advertised","errorCode":"paperclip_runner_tool_not_advertised","errorMessage":"paperclip_runner_tool_not_advertised","messagePattern":"paperclip_runner_tool_not_advertised","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/src/services/native-runtime/paperclip-runner-tool-authority.ts","lineNumber":279,"sourceCode":"            payload: { issueId: this.binding.issueId, mutation: \"connection_tools_refreshed\" },\n            idempotencyKey,\n            issueStateGuard: { statuses: [\"in_progress\", \"in_review\"], assigneeAgentId: this.binding.agentId },\n            requestedByActorType: \"agent\", requestedByActorId: this.binding.agentId,\n            contextSnapshot: { issueId: this.binding.issueId, taskId: this.binding.issueId, forceFreshSession: true, wakeReason: \"issue_assigned\", source: \"connection_tools.refreshed\" },\n          }); } catch (error) { if (!(await delivered()).length) throw error; }\n          return { ...result, instruction: \"Access is already authorized. A fresh continuation with updated tools is queued. Finish independent work, then yield. Do not request authorization again.\" };\n        }\n      }\n      return result;\n    }\n    if (\n      !IMPLEMENTED_OPERATIONS.has(call.tool) &&\n      call.tool !== READ_CURRENT_WAKE_COMMENTS_TOOL_NAME &&\n      call.tool !== LIST_CHAT_ATTACHMENTS_TOOL_NAME &&\n      call.tool !== REUSE_CHAT_ATTACHMENT_TOOL_NAME &&\n      call.tool !== READ_CHAT_ATTACHMENT_TOOL_NAME\n    ) {\n      throw new Error(\"paperclip_runner_tool_not_advertised\");\n    }\n    if (\n      !runnerApiToolsEnabled(\n        this.binding.companyId,\n        this.binding.apiToolsEnabled,\n      ) &&\n      [\"search_api\", \"call_api\"].includes(call.tool)\n    ) {\n      throw new Error(\"paperclip_runner_tool_not_advertised\");\n    }\n    const context = await this.#boundContext();\n    const input = record(call.arguments);\n    if (call.tool === READ_CHAT_ATTACHMENT_TOOL_NAME) {\n      const scope = this.binding.chatAttachmentReadScope;\n      const identityKeys = [\"companyId\", \"issueId\", \"runId\", \"agentId\"] as const;\n      if (!scope || identityKeys.some((key) => scope.options.binding[key] !== this.binding[key])) {\n        throw new Error(\"paperclip_runner_chat_attachment_read_scope_unavailable\");\n      }","sourceCodeStart":261,"sourceCodeEnd":297,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/server/src/services/native-runtime/paperclip-runner-tool-authority.ts#L261-L297","documentation":"PaperclipRunnerToolAuthority.execute validates every requested tool call against what the runner actually advertises. At paperclip-runner-tool-authority.ts:146 it throws 'paperclip_runner_tool_not_advertised' when the requested call.tool is not a connection tool (RUNTIME_CONNECTION_TOOL_DEFINITIONS) and is also not present in IMPLEMENTED_OPERATIONS — i.e. the agent invoked a tool name that is neither a runtime connection tool nor an implemented capability operation. This keeps the runner from executing tool names that were never advertised to the model.","triggerScenarios":"execute({tool, callId, arguments}) is called with a tool name that is neither in RUNTIME_CONNECTION_TOOL_DEFINITIONS nor in IMPLEMENTED_OPERATIONS — e.g. a typo'd tool name, a removed/renamed operation, a model-hallucinated tool, or a stale cached tool list referencing an old operationId.","commonSituations":"Model hallucinates a tool name not in its advertised list; server code renamed an operation while an old prompt/session still references the previous name; a plugin or adapter passes through arbitrary tool names; version skew between UI/adapter expectations and the deployed catalog.","solutions":["Check the tool name against the runner's advertised tools list (CAPABILITY_SEMANTIC_TOOL_CATALOG operationIds plus connection tools) and correct any typo or stale name.","Re-pull the current tool list for the run (toolsFor/advertised set) so the model only calls implemented operations, then retry in a fresh continuation.","If the operation should exist, add it to IMPLEMENTED_OPERATIONS and CAPABILITY_SEMANTIC_TOOL_CATALOG with an implemented handler.","If the call comes from a stale session/prompt, force a fresh session (forceFreshSession wakeup) with the updated tool catalog."],"exampleFix":"// before\nexecute({ tool: \"search_api_v2\", callId, arguments });\n// after\nexecute({ tool: \"search_api\", callId, arguments }); // name present in IMPLEMENTED_OPERATIONS","handlingStrategy":"validation","validationCode":"import { IMPLEMENTED_OPERATIONS, RUNTIME_CONNECTION_TOOL_DEFINITIONS } from \".../paperclip-runner-tool-authority\";\nfunction isCallableTool(tool: string): boolean {\n  return IMPLEMENTED_OPERATIONS.has(tool) || RUNTIME_CONNECTION_TOOL_DEFINITIONS.some((t) => t.name === tool);\n}\nif (!isCallableTool(call.tool)) throw new Error(`tool ${call.tool} is not advertised; pick one from the advertised tools list`);","typeGuard":"function isAdvertisedTool(tool: string, advertised: readonly { name: string }[]): tool is typeof advertised[number][\"name\"] {\n  return advertised.some((t) => t.name === tool);\n}","tryCatchPattern":"try {\n  return await authority.execute(call);\n} catch (err) {\n  if (err instanceof Error && err.message === \"paperclip_runner_tool_not_advertised\") {\n    return { error: \"tool_not_available\", hint: \"Re-read get_task_context/tools list and choose an advertised tool.\" };\n  }\n  throw err;\n}","preventionTips":["Always derive model-facing tool lists from the same IMPLEMENTED_OPERATIONS/catalog source the executor checks.","Validate tool names against the advertised list before dispatching calls from adapters/plugins.","Force a fresh session when the server's tool catalog changes so old tool names are not replayed.","Add a fuzz/unit test that dispatches every catalog operationId through execute()."],"tags":["tool-not-implemented","hallucinated-tool","tool-catalog","agent-runtime"],"backgroundTag":"unsupported-operation","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}