JuliusBrussee/caveman · error
encode before evidence: %w
Error message
encode before evidence: %w
What it means
json.Marshal of the before-evidence map failed in RecordAppliedFix, before any database write. The map copies the sink's evidence and adds before_source; marshaling fails only if evidence contains values JSON cannot encode (channels, funcs, cyclic data).
Source
Thrown at proxy/internal/store/learn_outcomes.go:93
}
if fixKind == "" {
return AppliedFixRecord{}, fmt.Errorf("sink %q has no measurable fix kind; pass --fix-kind explicitly", sinkID)
}
if len(fixKind) > 128 {
return AppliedFixRecord{}, fmt.Errorf("fix kind exceeds 128 bytes")
}
if len(note) > 4096 {
return AppliedFixRecord{}, fmt.Errorf("note exceeds 4096 bytes")
}
appliedAt := appliedAtTime.Format(time.RFC3339)
beforeEvidence := make(map[string]any, len(sink.Evidence)+1)
for key, value := range sink.Evidence {
beforeEvidence[key] = value
}
beforeEvidence["before_source"] = beforeSource
evidence, err := json.Marshal(beforeEvidence)
if err != nil {
return AppliedFixRecord{}, fmt.Errorf("encode before evidence: %w", err)
}
// Fingerprint the edited artifact as it stands NOW — which at
// `caveman learn applied` time is immediately after the approved edit. This
// is the provenance anchor: a later scan re-hashes the same path and can
// state whether the change we proposed is still the change that is there.
target := fingerprintFixTarget(*sink)
targetJSON := ""
if target != nil {
if encoded, encodeErr := json.Marshal(target); encodeErr == nil {
targetJSON = string(encoded)
}
}
result, err := s.db.Exec(`INSERT INTO applied_fixes
(sink_id, practice_id, fix_kind, applied_at, before_tokens_per_turn, before_evidence_json, note, target_json)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, sink.SinkID, sink.PracticeID, fixKind, appliedAt, sink.TokensPerTurn, string(evidence), note, targetJSON)
if err != nil {
return AppliedFixRecord{}, fmt.Errorf("record applied fix: %w", err)
}View on GitHub (pinned to 81536f57b3)
Solutions
- Inspect the sink evidence map for non-JSON-serializable values
- Sanitize or drop unsupported evidence values before recording the fix
- Log the wrapped json error to identify the offending key
Defensive patterns
Strategy: fallback
When it happens
Trigger: Thrown at proxy/internal/store/learn_outcomes.go:93 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of JuliusBrussee/caveman@81536f57b3 (2026-08-27).
Data as JSON: /api/errors/5e92cdd4bdc08e18.
Report an issue: GitHub.