sipeed/picoclaw · error
configure process hook %q: %w
Error message
configure process hook %q: %w
What it means
Every enabled entry in hooks.processes is validated by processHookOptionsFromConfig before anything launches. This wrapper means validation failed for that hook: transport is not 'stdio', command is empty, an observe entry is not a known event kind, an intercept entry is unsupported, or no hook mode is enabled at all. The unwrapped message says which constraint failed.
Source
Thrown at pkg/agent/hook_mount.go:170
return fmt.Errorf("build builtin hook %q: %w", name, factoryErr)
}
if err := al.MountHook(HookRegistration{
Name: name,
Priority: spec.Priority,
Source: HookSourceInProcess,
Hook: hook,
}); err != nil {
return fmt.Errorf("mount builtin hook %q: %w", name, err)
}
mounted = append(mounted, name)
}
processNames := enabledProcessHookNames(al.cfg.Hooks.Processes)
for _, name := range processNames {
spec := al.cfg.Hooks.Processes[name]
opts, buildErr := processHookOptionsFromConfig(spec)
if buildErr != nil {
return fmt.Errorf("configure process hook %q: %w", name, buildErr)
}
processHook, buildErr := NewProcessHook(ctx, name, opts)
if buildErr != nil {
return fmt.Errorf("start process hook %q: %w", name, buildErr)
}
if err := al.MountHook(HookRegistration{
Name: name,
Priority: spec.Priority,
Source: HookSourceProcess,
Hook: processHook,
}); err != nil {
_ = processHook.Close()
return fmt.Errorf("mount process hook %q: %w", name, err)
}
mounted = append(mounted, name)
}
View on GitHub (pinned to 49183d7e8d)
Solutions
- Read the unwrapped inner message — it names the exact failed constraint
- Set transport to "stdio" or remove the field (it is the default)
- Provide command as a non-empty argv array
- Use valid observe kinds (runtime event names such as tool_exec_start, turn_end, or '*' for all)
- Enable at least one mode: observe non-empty or intercept containing before_llm/after_llm/before_tool/after_tool/approve_tool
Example fix
// before
"processes": { "audit": { "enabled": true, "transport": "grpc",
"command": [], "intercept": ["before_llm"] } }
// after
"processes": { "audit": { "enabled": true,
"command": ["/usr/local/bin/audit-hook"],
"intercept": ["before_llm"] } } Defensive patterns
Strategy: validation
Validate before calling
validIntercept := map[string]bool{"before_llm": true, "after_llm": true, "before_tool": true, "after_tool": true, "approve_tool": true}
for name, p := range cfg.Hooks.Processes {
if !p.Enabled {
continue
}
if p.Transport != "" && p.Transport != "stdio" {
return fmt.Errorf("hooks.processes.%s: only stdio transport supported", name)
}
if len(p.Command) == 0 {
return fmt.Errorf("hooks.processes.%s: command required", name)
}
hasMode := len(p.Observe) > 0 || len(p.Intercept) > 0
for _, it := range p.Intercept {
if !validIntercept[it] {
return fmt.Errorf("hooks.processes.%s: bad intercept %q", name, it)
}
}
if !hasMode {
return fmt.Errorf("hooks.processes.%s: enable observe or intercept", name)
}
} Prevention
- Run this validation as a config lint before deploy — all sub-errors (transport/command/observe/intercept/modes) are caught here
- Use event names from the runtime events list (e.g. tool_exec_start) or '*' for observe
- Remember a process hook with neither observe nor intercept is always rejected
When it happens
Trigger: A hooks.processes.<name> entry with enabled=true and any of: transport set to something other than "stdio" (empty is fine), command missing/empty, observe listing invalid kinds, intercept outside {before_llm, after_llm, before_tool, after_tool, approve_tool}, or all of observe/intercept left empty ('no hook modes enabled').
Common situations: Assuming network transports (http/grpc) exist for hooks like they do for MCP; enabling a process hook before writing its command; event-kind typos like 'tool_start' instead of 'tool_exec_start'; forgetting that a process hook must observe or intercept something.
Related errors
- command is required
- build builtin hook %q: %w
- unsupported transport %q
- tool discovery is enabled but neither 'use_bm25' nor 'use_re
- builtin hook %q is not registered
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/630ace8b785a033c.
Report an issue: GitHub.