{"record":{"id":"9560647b139dbf97","repo":"sipeed/picoclaw","slug":"builtin-hook-q-is-not-registered","errorCode":null,"errorMessage":"builtin hook %q is not registered","messagePattern":"builtin hook %q is not registered","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/agent/hook_mount.go","lineNumber":147,"sourceCode":"\t}\n\n\tmounted := make([]string, 0)\n\tdefer func() {\n\t\tif err != nil {\n\t\t\tfor _, name := range mounted {\n\t\t\t\tal.UnmountHook(name)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tal.hookRuntime.setMounted(mounted)\n\t}()\n\n\tbuiltinNames := enabledBuiltinHookNames(al.cfg.Hooks.Builtins)\n\tfor _, name := range builtinNames {\n\t\tspec := al.cfg.Hooks.Builtins[name]\n\t\tfactory, ok := lookupBuiltinHook(name)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"builtin hook %q is not registered\", name)\n\t\t}\n\n\t\thook, factoryErr := factory(ctx, spec)\n\t\tif factoryErr != nil {\n\t\t\treturn fmt.Errorf(\"build builtin hook %q: %w\", name, factoryErr)\n\t\t}\n\t\tif err := al.MountHook(HookRegistration{\n\t\t\tName:     name,\n\t\t\tPriority: spec.Priority,\n\t\t\tSource:   HookSourceInProcess,\n\t\t\tHook:     hook,\n\t\t}); err != nil {\n\t\t\treturn fmt.Errorf(\"mount builtin hook %q: %w\", name, err)\n\t\t}\n\t\tmounted = append(mounted, name)\n\t}\n\n\tprocessNames := enabledProcessHookNames(al.cfg.Hooks.Processes)","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/pkg/agent/hook_mount.go#L129-L165","documentation":"At startup, every name enabled under hooks.builtins is looked up in an in-process registry populated by agent.RegisterBuiltinHook. picoclaw itself registers no builtins in the default build — they are an extension point for embeddings — so this error means config enables a builtin hook name that no RegisterBuiltinHook call in your binary provides (typo, renamed hook, or a missing side-effect import of the package that registers it).","triggerScenarios":"hooks.enabled=true and hooks.builtins.<name>.enabled=true where <name> has no registered factory: misspelled name, a hook from a newer picoclaw version, or an extension package that registers the hook was never imported (so its init() never ran).","commonSituations":"Copying hooks config from docs of a different version; forks that dropped builtin hooks; forgetting that registration happens via package side effects, so dead-code elimination or a missing import silently drops the factory.","solutions":["List the names your binary actually registers (grep your code for RegisterBuiltinHook calls) and fix the config name to match","Import the package that calls RegisterBuiltinHook for that hook so its init() runs before startup","Update picoclaw/embedding to the version that provides the hook you configured","Set enabled=false for the unknown entry if the hook is not needed"],"exampleFix":"// before — config enables a name nothing registers\n\"hooks\": { \"enabled\": true, \"builtins\": { \"auditspell\": { \"enabled\": true } } }\n\n// after — name matches the registration\nimport picoclawhooks \"yourcorp/picoclaw-extra-hooks\" // registers \"audit_spell\"\n\n\"hooks\": { \"enabled\": true, \"builtins\": { \"audit_spell\": { \"enabled\": true } } }","handlingStrategy":"validation","validationCode":"registered := map[string]bool{\n    // keep in sync with every RegisterBuiltinHook call linked into the binary\n    \"audit_spell\": true,\n}\nfor name, spec := range cfg.Hooks.Builtins {\n    if spec.Enabled && !registered[name] {\n        return fmt.Errorf(\"hooks.builtins.%s: no factory registered in this build\", name)\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Import every package that calls RegisterBuiltinHook from your main package so registration side effects always run","Maintain a name allowlist and validate hooks config against it in CI","After upgrading picoclaw or hook extensions, diff the registered-hook list against config"],"tags":["go","picoclaw","hooks","config","extension-registry"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}