sipeed/picoclaw · error
unsupported observe event %q
Error message
unsupported observe event %q
What it means
Thrown by processHookObserveKindsFromConfig while normalizing a hook's `observe` list. Each entry must be "*"/"all" (wildcard, enables observing everything) or a known hook event kind from validHookEventKinds(): the runtime event kinds plus turn_start, turn_end, llm_request, llm_delta, llm_response, llm_retry, context_compress, session_summarize, tool_exec_start, tool_exec_end, tool_exec_skipped, steering_injected, follow_up_queued, interrupt_received, subturn_spawn, subturn_end, subturn_result_delivered, subturn_orphan, error.
Source
Thrown at pkg/agent/hook_mount.go:301
}
return env
}
func processHookObserveKindsFromConfig(observe []string) ([]string, bool, error) {
if len(observe) == 0 {
return nil, false, nil
}
validKinds := validHookEventKinds()
normalized := make([]string, 0, len(observe))
for _, kind := range observe {
switch kind {
case "", "*", "all":
return nil, true, nil
default:
normalizedKind, ok := validKinds[kind]
if !ok {
return nil, false, fmt.Errorf("unsupported observe event %q", kind)
}
normalized = append(normalized, normalizedKind)
}
}
if len(normalized) == 0 {
return nil, false, nil
}
return normalized, true, nil
}
func validHookEventKinds() map[string]string {
runtimeKinds := runtimeevents.KnownKinds()
kinds := make(map[string]string, len(runtimeKinds)*2)
for _, kind := range runtimeKinds {
kinds[kind.String()] = kind.String()
}
kinds["turn_start"] = runtimeevents.KindAgentTurnStart.String()View on GitHub (pinned to 49183d7e8d)
Solutions
- Use a supported event kind exactly as spelled in validHookEventKinds (underscores, lowercase), e.g. llm_response, tool_exec_end
- Use "*" or "all" if you want every event instead of listing names
- If the value looks correct, check the library version — the kind may have been renamed; update to the current name
Example fix
# before
hooks:
process:
my-hook:
command: ["./hook"]
observe: ["turn-start", "tool_call"]
# after
hooks:
process:
my-hook:
command: ["./hook"]
observe: ["turn_start", "tool_exec_start"] Defensive patterns
Strategy: validation
Validate before calling
func validateObserveKinds(observe []string) error {
valid := validHookEventKinds()
for _, k := range observe {
switch k {
case "", "*", "all":
continue
default:
if _, ok := valid[k]; !ok {
return fmt.Errorf("observe event %q unknown; use a known kind or \"*\"", k)
}
}
}
return nil
} Try / catch
opts, err := processHookOptionsFromConfig(spec)
if err != nil {
return fmt.Errorf("hook %q observe config invalid: %w", name, err)
} Prevention
- Prefer observe: ["*"] unless you need filtering
- Use underscores and lowercase event names (turn_start, not turn-start)
- Re-validate observe lists after upgrading the library — event kinds evolve
When it happens
Trigger: A hook config with observe: ["turn-start"] (hyphen instead of underscore), "tool_call", "message", or any event name not in the valid kinds map. Match is exact and case-sensitive; only "", "*", and "all" are special-cased.
Common situations: Guessing event names instead of checking the supported list; using provider/webhook event vocabulary; event kinds renamed or added between library versions so a previously valid kind stops resolving.
Related errors
- build builtin hook %q: %w
- configure process hook %q: %w
- command is required
- unsupported intercept %q
- no hook modes enabled
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/99257eb54bb6fd93.
Report an issue: GitHub.