JuliusBrussee/caveman · error

native hook payload too large

Error message

native hook payload too large

What it means

readNativeHookPayload streams stdin in 16 KiB chunks and enforces nativeHookMaxPayloadBytes as a hard cap on the total JSON payload. When accumulated bytes would exceed the cap, it fails fast with "native hook payload too large". This protects the proxy from unbounded stdin input from Claude Code native hook events.

Solutions

  1. Reduce the hook payload size (trim tool output, disable verbose fields in hook config).
  2. Check nativeHookMaxPayloadBytes and, if legitimately needed, raise the limit via configuration.
  3. Inspect the hook command in the Claude Code settings for accidental file redirection into stdin.
  4. Log/truncate payload content upstream before invoking the proxy hook bridge.

Example fix

// before (hook config)
"command": "cat "$TOOL_OUTPUT" | caveman-proxy native-hook"
// after
"command": "head -c 60000 "$TOOL_OUTPUT" | caveman-proxy native-hook"
Defensive patterns

Strategy: validation

Validate before calling

// before piping to the native hook bridge
const maxPayload = 64 * 1024 // match nativeHookMaxPayloadBytes
if stat, err := os.Stdin.Stat(); err == nil && stat.Size() > int64(maxPayload) {
    return errors.New("hook input exceeds payload limit; truncate first")
}

Try / catch

payload, err := readNativeHookPayload(r)
if err != nil && err.Error() == "native hook payload too large" {
    log.Printf("hook payload rejected; trim hook output and retry")
}

Prevention

When it happens

Trigger: The native hook bridge (runNativeHookBridge) receives a hook payload larger than nativeHookMaxPayloadBytes — e.g. a hook emitting huge tool output or a misconfigured hook piping an entire file into stdin.

Common situations: A PostToolUse/Stop hook whose JSON includes massive transcript or tool-result content; users piping debug dumps into caveman-proxy's native hook mode.

Understand the failure class

Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/d666a281fba08a05. Report an issue: GitHub.

Appendix: source

Thrown at proxy/cmd/caveman-proxy/main.go:117

			return
		}
		home = filepath.Join(userHome, ".caveman")
	}
	raw, err := readNativeHookPayload(os.Stdin)
	if err != nil || len(raw) > nativeHookMaxPayloadBytes {
		return
	}
	_ = nativehook.Run(context.Background(), home, agent, adapter, raw, os.Stdout, os.Stderr)
}

func readNativeHookPayload(r io.Reader) ([]byte, error) {
	raw := make([]byte, 0, 4096)
	buf := make([]byte, 16*1024)
	for {
		n, err := r.Read(buf)
		if n > 0 {
			if len(raw)+n > nativeHookMaxPayloadBytes {
				return nil, fmt.Errorf("native hook payload too large")
			}
			raw = append(raw, buf[:n]...)
			if json.Valid(raw) {
				return raw, nil
			}
		}
		if err != nil {
			if err == io.EOF {
				return raw, nil
			}
			return nil, err
		}
	}
}

func runNativeWhy(logger *slog.Logger, args []string) {
	decisionID := argFlag(args, "--decision", "")
	if decisionID == "" && len(args) == 1 && !strings.HasPrefix(args[0], "-") {

View on GitHub (pinned to 3ee70a1026)