sipeed/picoclaw · error
process hook %q %s failed: %s
Error message
process hook %q %s failed: %s
What it means
Returned by ProcessHook.call when the hook subprocess answered the JSON-RPC request with an error object (resp.Error != nil). This is a well-formed, protocol-level failure reported by the hook itself — the message after "failed:" is the hook's own error text for the named method.
Source
Thrown at pkg/agent/hook_process.go:361
if err != nil {
ph.removePending(id)
return err
}
msg.Params = body
}
if err := ph.send(ctx, msg); err != nil {
ph.removePending(id)
return err
}
select {
case resp, ok := <-respCh:
if !ok {
return fmt.Errorf("process hook %q closed while waiting for %s", ph.name, method)
}
if resp.Error != nil {
return fmt.Errorf("process hook %q %s failed: %s", ph.name, method, resp.Error.Message)
}
if out != nil && len(resp.Result) > 0 {
if err := json.Unmarshal(resp.Result, out); err != nil {
return fmt.Errorf("decode process hook %q %s result: %w", ph.name, method, err)
}
}
return nil
case <-ctx.Done():
ph.removePending(id)
return ctx.Err()
}
}
func (ph *ProcessHook) send(ctx context.Context, msg processHookRPCMessage) error {
body, err := json.Marshal(msg)
if err != nil {
return err
}View on GitHub (pinned to 49183d7e8d)
Solutions
- Read the trailing hook-provided message — it names the real cause; fix the condition inside the hook implementation
- Log the hook's stderr, which usually carries the stack trace or detail behind the RPC error
- If caused by params the hook doesn't understand, align hook and host versions so method schemas match
- For policy hooks (approve_tool), verify the rejection is intentional vs. an internal hook bug
Defensive patterns
Strategy: try-catch
Type guard
func isHookRPCError(err error) bool {
return err != nil && strings.Contains(err.Error(), " failed: ")
} Try / catch
err := ph.CallApproveTool(ctx, payload)
if err != nil {
if isHookRPCError(err) {
// hook-side logic error: log and apply your policy default (deny/approve)
log.Printf("approval hook rejected: %v", err)
return ErrToolDenied
}
return err
} Prevention
- Log the full hook error message plus the hook's stderr on every RPC failure
- Pin host and hook versions together so method semantics stay aligned
- Define a safe default (e.g. deny) for when a policy hook errors
When it happens
Trigger: Any hook-side method handler returning an error: an approve_tool hook rejecting/ failing to evaluate a tool call, a before_llm hook failing to parse its params, or the hook deliberately refusing an operation. The RPC transport itself worked; the hook's logic did not.
Common situations: Hook's internal validation rejects input (unknown tool name, malformed request); hook's downstream dependency (policy server, secret store) unavailable; version skew where the hook receives a method or params schema it doesn't implement.
Related errors
- process hook %q is closed
- process hook %q closed while waiting for %s
- decode process hook %q %s result: %w
- write process hook %q message: %w
- builtin hook %q is not registered
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/620be93b14322ee7.
Report an issue: GitHub.