{"record":{"id":"f5ecf8ecb57b7c60","repo":"sipeed/picoclaw","slug":"build-builtin-hook-q-w","errorCode":null,"errorMessage":"build builtin hook %q: %w","messagePattern":"build builtin hook %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/agent/hook_mount.go","lineNumber":152,"sourceCode":"\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)\n\tfor _, name := range processNames {\n\t\tspec := al.cfg.Hooks.Processes[name]\n\t\topts, buildErr := processHookOptionsFromConfig(spec)\n\t\tif buildErr != nil {\n\t\t\treturn fmt.Errorf(\"configure process hook %q: %w\", name, buildErr)","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/pkg/agent/hook_mount.go#L134-L170","documentation":"The factory for an enabled builtin hook ran but rejected its spec: the hooks.builtins.<name>.config JSON blob failed that hook's own validation. The factory's error is wrapped with the hook name, so the inner message names the exact field or value the hook rejected. Initialization aborts and no further hooks mount.","triggerScenarios":"hooks.builtins.<name>.enabled=true with a config object whose fields are missing, wrong-typed, or out of range for that hook's schema (each RegisterBuiltinHook factory defines its own).","commonSituations":"Hand-editing hook config JSON; schema drift after upgrading the package providing the hook; nesting settings one level too deep/shallow; passing strings where numbers are expected.","solutions":["Read the wrapped error after the hook name — it identifies the invalid field/value","Check the hook provider's documentation for the expected config schema and correct the JSON","Validate the config fragment parses (json.Unmarshal into the hook's options struct) in a scratch program or CI","After upgrading the hook package, re-check for renamed fields"],"exampleFix":"// before — threshold passed as string\n\"builtins\": { \"audit_spell\": { \"enabled\": true, \"config\": { \"threshold\": \"0.8\" } } }\n\n// after — correct type\n\"builtins\": { \"audit_spell\": { \"enabled\": true, \"config\": { \"threshold\": 0.8 } } }","handlingStrategy":"try-catch","validationCode":"for name, spec := range cfg.Hooks.Builtins {\n    if !spec.Enabled || len(spec.Config) == 0 {\n        continue\n    }\n    var probe any\n    if err := json.Unmarshal(spec.Config, &probe); err != nil {\n        return fmt.Errorf(\"hooks.builtins.%s: config is not valid JSON: %w\", name, err)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := al.EnsureHooksInitialized(ctx); err != nil {\n    if hookErr, ok := unwrapPrefix(err, \"build builtin hook\"); ok {\n        // config/schema problem: fix config and restart; do not retry blindly\n        log.Printf(\"hook config rejected: %v\", hookErr)\n    }\n}","preventionTips":["Unmarshal each hook's config JSON into the hook's options struct in a config-lint step","Pin hook extension versions so config schemas cannot drift under you","Prefer small config surfaces; unknown extra keys usually mean nesting mistakes"],"tags":["go","picoclaw","hooks","config","validation"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}