{"record":{"id":"b921ef13e5fec40a","repo":"vxcontrol/pentagi","slug":"unknown-tool-s-b921ef","errorCode":null,"errorMessage":"unknown tool: %s","messagePattern":"unknown tool: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/tools/terminal.go","lineNumber":186,"sourceCode":"\t\t\t\"path\":   action.Path,\n\t\t})\n\n\t\tswitch action.Action {\n\t\tcase ReadFile:\n\t\t\tresult, err := t.ReadFile(ctx, t.flowID, action.Path.String())\n\t\t\treturn t.wrapCommandResult(ctx, args, name, result, err)\n\t\tcase WriteFile:\n\t\t\tresult, err := t.WriteFile(ctx, t.flowID, action.Content, action.Path.String())\n\t\t\treturn t.wrapCommandResult(ctx, args, name, result, err)\n\t\tcase EditFile:\n\t\t\tresult, err := t.EditFile(ctx, t.flowID, action.Path.String(), action.Diff.String())\n\t\t\treturn t.wrapCommandResult(ctx, args, name, result, err)\n\t\tdefault:\n\t\t\tlogger.Error(\"unknown file action\")\n\t\t\treturn \"\", fmt.Errorf(\"unknown file action: %s\", action.Action)\n\t\t}\n\tdefault:\n\t\treturn \"\", fmt.Errorf(\"unknown tool: %s\", name)\n\t}\n}\n\nfunc (t *terminal) ExecCommand(\n\tctx context.Context,\n\tcwd, command string,\n\tdetach bool,\n\ttimeout time.Duration,\n) (string, error) {\n\tcontainerName := PrimaryTerminalName(t.tenantPrefix, t.flowID)\n\n\tcmd := []string{\n\t\t\"sh\",\n\t\t\"-c\",\n\t\tcommand,\n\t}\n\n\tisRunning, err := t.dockerClient.IsContainerRunning(ctx, t.containerLID)","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/tools/terminal.go#L168-L204","documentation":"Handle dispatches a tool call by its name; the outer switch only knows ExecToolName and FileToolName. If the LLM or caller supplies any other tool name, the terminal wrapper returns \"unknown tool: %s\" naming the unrecognized tool. It is a dispatch-level guard, not a runtime failure.","triggerScenarios":"Calling terminal.Handle with a name other than \"exec\" or \"file\" — e.g. a typo in the tool name registered with the LLM, a stale tool registry, or the LLM hallucinating a tool name like \"shell\" or \"read_file\".","commonSituations":"Prompt/tool schema mismatch after renaming a tool; an agent model inventing a tool not in the registered list; wiring the same handler into a provider whose tool list was updated independently.","solutions":["Check the tool name string passed to Handle against the registered constants (ExecToolName, FileToolName) — fix typos or case mismatches","Ensure the tool list advertised to the LLM exactly matches the names Handle dispatches on","Add the missing case to the switch if the tool is legitimately new"],"exampleFix":"// before\nresult, err := terminal.Handle(ctx, \"shell\", args) // unknown tool: shell\n// after\nresult, err := terminal.Handle(ctx, tools.ExecToolName, args)","handlingStrategy":"validation","validationCode":"func validateToolName(name string) error {\n    switch name {\n    case tools.ExecToolName, tools.FileToolName:\n        return nil\n    default:\n        return fmt.Errorf(\"unsupported tool %q; must be %q or %q\", name, tools.ExecToolName, tools.FileToolName)\n    }\n}\nif err := validateToolName(name); err != nil { return err }","typeGuard":"func isKnownTool(name string) bool {\n    return name == tools.ExecToolName || name == tools.FileToolName\n}","tryCatchPattern":"result, err := terminal.Handle(ctx, name, args)\nif err != nil {\n    if strings.HasPrefix(err.Error(), \"unknown tool:\") {\n        // fall back to a known tool or report schema mismatch to the orchestrator\n        return handleUnknownTool(ctx, name, args)\n    }\n    return err\n}","preventionTips":["Always reference tool-name constants instead of raw string literals","Keep the tool schema advertised to the LLM generated from the same constants Handle dispatches on","Log the full args payload on unknown-tool errors to catch hallucinated names early"],"tags":["tool-dispatch","llm-agents","argument-validation"],"backgroundTag":"unknown-tool-name","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}