JuliusBrussee/caveman · error

native runtime: unknown policy mode

Error message

native runtime: unknown policy mode %q

What it means

Handle validates request.PolicyMode after defaulting an empty value to "safe". Only "record", "safe", and "max" are accepted; any other string is rejected with this error. This keeps policy selection restricted to the supported profiles.

Solutions

  1. Set PolicyMode to one of exactly "record", "safe", or "max"
  2. Fix the config/env value casing and spelling (values are case-sensitive, lowercase)
  3. Leave PolicyMode empty ("") to get the default "safe" mode

Example fix

// before
req.PolicyMode = "Strict"
// after
req.PolicyMode = "max" // or "record" / "safe"
Defensive patterns

Strategy: validation

Validate before calling

var validModes = map[string]bool{"": true, "record": true, "safe": true, "max": true}
if !validModes[req.PolicyMode] {
	return fmt.Errorf("invalid policy mode %q", req.PolicyMode)
}

Type guard

func validPolicyMode(m string) bool { return m == "" || m == "record" || m == "safe" || m == "max" }

Prevention

When it happens

Trigger: Calling Handle with PolicyMode set to anything other than "", "record", "safe", or "max" (e.g. "strict", "SAFE", "paranoid" from config or env).

Common situations: Config file or environment variable carrying a policy name from a different tool; case mismatches; user edits to policy settings.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at proxy/internal/nativeruntime/runtime.go:225

	sessionLock := r.sessionLock(request.Session.ID)
	sessionLock.Lock()
	defer sessionLock.Unlock()

	if request.ProtocolVersion != ProtocolVersion {
		return Response{}, fmt.Errorf("native runtime: unsupported protocol version %d", request.ProtocolVersion)
	}
	if _, ok := eventTypes[request.Event.Type]; !ok {
		return Response{}, fmt.Errorf("native runtime: unknown event %q", request.Event.Type)
	}
	if strings.TrimSpace(request.Session.ID) == "" {
		return Response{}, errors.New("native runtime: session id is required")
	}
	policyMode := request.PolicyMode
	if policyMode == "" {
		policyMode = "safe"
	}
	if policyMode != "record" && policyMode != "safe" && policyMode != "max" {
		return Response{}, fmt.Errorf("native runtime: unknown policy mode %q", policyMode)
	}
	request.PolicyMode = policyMode
	profile, features, err := resolveProfile(request.Profile, policyMode)
	if err != nil {
		return Response{}, err
	}
	request.Profile = profile
	r.mu.Lock()
	r.lastActivity = time.Now()
	// Listener lifetime is independent of session bookkeeping. Prune abandoned
	// correlation entries lazily so a persistent proxy does not retain them
	// forever when a host disappears without session.end.
	for sessionID, activity := range r.activeSessions {
		if r.lastActivity.Sub(activity.At) >= 30*time.Minute {
			delete(r.activeSessions, sessionID)
		}
	}
	if request.Event.Type == "session.end" {

View on GitHub (pinned to 3ee70a1026)