{"record":{"id":"bcf4af323bd9c9ae","repo":"vxcontrol/pentagi","slug":"handler-for-function-s-not-found","errorCode":null,"errorMessage":"handler for function %s not found","messagePattern":"handler for function (.+?) not found","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/tools/tools.go","lineNumber":778,"sourceCode":"\t}\n\n\t// TODO: here better to get flow containers list and purge all of them\n\tif err := fte.docker.RemoveContainer(ctx, fte.primaryLID, fte.primaryID); err != nil {\n\t\tcontainerName := PrimaryTerminalName(fte.cfg.TenantPrefix(), fte.flowID)\n\t\treturn fmt.Errorf(\"failed to purge container '%s': %w\", containerName, err)\n\t}\n\n\treturn nil\n}\n\nfunc (fte *flowToolsExecutor) GetCustomExecutor(cfg CustomExecutorConfig) (ContextToolsExecutor, error) {\n\tif len(cfg.Definitions) != len(cfg.Handlers) {\n\t\treturn nil, fmt.Errorf(\"definitions and handlers must have the same length\")\n\t}\n\n\tfor _, def := range cfg.Definitions {\n\t\tif _, ok := cfg.Handlers[def.Name]; !ok {\n\t\t\treturn nil, fmt.Errorf(\"handler for function %s not found\", def.Name)\n\t\t}\n\t}\n\n\tfor _, builtin := range cfg.Builtin {\n\t\tif def, ok := fte.definitions[builtin]; !ok {\n\t\t\treturn nil, fmt.Errorf(\"builtin function %s not found\", builtin)\n\t\t} else {\n\t\t\tcfg.Definitions = append(cfg.Definitions, def)\n\t\t\tcfg.Handlers[builtin] = fte.handlers[builtin]\n\t\t}\n\t}\n\n\tbarriers := make(map[string]struct{})\n\tfor _, barrier := range cfg.Barriers {\n\t\tif _, ok := fte.handlers[barrier]; !ok {\n\t\t\treturn nil, fmt.Errorf(\"barrier function %s not found\", barrier)\n\t\t}\n\t\tbarriers[barrier] = struct{}{}","sourceCodeStart":760,"sourceCodeEnd":796,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/tools/tools.go#L760-L796","documentation":"After the length check, GetCustomExecutor iterates every FunctionDefinition in cfg.Definitions and requires a handler keyed by def.Name in cfg.Handlers. If a definition lacks a handler, the executor cannot dispatch calls to that function, so it refuses to build the custom executor with this named error.","triggerScenarios":"Calling GetCustomExecutor with a definition whose Name has no entry in cfg.Handlers — typically when Definitions and Handlers are maintained by hand and a handler key is misspelled relative to the definition name, or a handler was deleted while the definition remained.","commonSituations":"Typo mismatch between def.Name (\"web_search\") and handler key (\"websearch\"); refactoring a tool name in the definition but not the handler map; conditionally registering definitions while handlers are built unconditionally (or vice versa).","solutions":["Add a handler in cfg.Handlers keyed exactly by the definition's Name reported in the error message.","Fix key/name mismatches by generating Handlers keys from def.Name programmatically.","Add a unit test that builds the CustomExecutorConfig and asserts GetCustomExecutor returns no error."],"exampleFix":"// before\nDefinitions: []tools.FunctionDefinition{{Name: \"port_scan\"}},\nHandlers:    map[string]tools.Handler{\"scan_port\": hScan},\n\n// after\nDefinitions: []tools.FunctionDefinition{{Name: \"port_scan\"}},\nHandlers:    map[string]tools.Handler{\"port_scan\": hScan},","handlingStrategy":"validation","validationCode":"for _, def := range cfg.Definitions {\n    if _, ok := cfg.Handlers[def.Name]; !ok {\n        return fmt.Errorf(\"definition %q has no handler\", def.Name)\n    }\n}","typeGuard":"func allHandlersPresent(cfg tools.CustomExecutorConfig) bool {\n    for _, d := range cfg.Definitions {\n        if _, ok := cfg.Handlers[d.Name]; !ok {\n            return false\n        }\n    }\n    return true\n}","tryCatchPattern":"executor, err := flowTools.GetCustomExecutor(cfg)\nif err != nil && strings.Contains(err.Error(), \"handler for function\") {\n    // fix the tool registration table named in the error before retrying\n    return fmt.Errorf(\"tool registration bug: %w\", err)\n}","preventionTips":["Always key the Handlers map from def.Name, never by hand-typed strings.","Keep each tool's definition and handler adjacent in code (same struct literal) so they change together.","Cover every registered tool with a build-time or test-time check that handlers resolve."],"tags":["go","validation","tools-api"],"backgroundTag":"missing-handler-registration","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}