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

  1. Read the trailing hook-provided message — it names the real cause; fix the condition inside the hook implementation
  2. Log the hook's stderr, which usually carries the stack trace or detail behind the RPC error
  3. If caused by params the hook doesn't understand, align hook and host versions so method schemas match
  4. 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

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


AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15). Data as JSON: /api/errors/620be93b14322ee7. Report an issue: GitHub.