Hmbown/CodeWhale · error
memory edits require non-empty evidence
Error message
memory edits require non-empty evidence
What it means
normalize_evidence requires every in-place memory edit (revise/retire) to carry non-empty evidence that passes the same normalization/bounds rules as a note. Empty, whitespace-only, or over-limit evidence is rejected: an unexplained rewrite of durable context is exactly what the journal is designed to prevent.
Solutions
- Provide a meaningful, non-empty evidence string explaining why the memory is being revised or retired.
- Keep evidence within the same limits as notes (line count/size) — trim verbose justification.
- At the tool/UI layer, require an evidence field before submitting the edit.
Example fix
// before memory.retire(scope, Some(ws), id, "")?; // after memory.retire(scope, Some(ws), id, "superseded by entry 42; fact no longer holds after refactor")?;
Defensive patterns
Strategy: validation
Validate before calling
fn validate_evidence(evidence: &str) -> Result<()> {
let t = evidence.trim();
if t.is_empty() { bail!("evidence required for memory edits"); }
Ok(())
} Try / catch
match memory.retire(scope, ws, id, evidence) {
Err(e) if e.to_string().contains("non-empty evidence") => {
eprintln!("Provide a reason: why is this memory being retired?");
}
other => other?,
} Prevention
- Make evidence a mandatory field in any UI/tool that calls revise or retire.
- Reject blank/whitespace input at the form layer before submission.
- Keep evidence within note bounds — brief, factual justification.
- Journal edits always with a reason; it is the audit trail for durable context changes.
When it happens
Trigger: Calling revise or retire with evidence = "" or whitespace, or evidence that fails normalize_note (e.g. exceeds size/line bounds after \r\n normalization); normalize_note returns Err and it is mapped to this message.
Common situations: Automated tooling calling retire without a reason; a UI that leaves the evidence field blank; programmatic cleanup scripts editing memories without justification.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- memory note is empty
- base URL cannot be empty
- browser URL cannot be empty
- classifier-approved read command was empty
- Codewhale runtime event file is empty.
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/15c06b542f9e17da.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/native_memory.rs:876
several.len()
),
}
}
/// The note body of a Markdown bullet, if the line is one.
fn bullet_text(line: &str) -> Option<&str> {
let trimmed = line.trim();
trimmed
.strip_prefix("- ")
.or_else(|| trimmed.strip_prefix("* "))
.map(str::trim)
}
/// Evidence is required on every in-place edit and held to the same bounds
/// as a note. An unexplained rewrite of durable context is the thing the
/// journal exists to prevent.
fn normalize_evidence(evidence: &str) -> Result<String> {
normalize_note(evidence).map_err(|_| anyhow!("memory edits require non-empty evidence"))
}
fn normalize_note(note: &str) -> Result<String> {
let note = note.replace("\r\n", "\n").replace('\r', "\n");
let note = note
.lines()
.map(str::trim)
.filter(|line| !line.is_empty())
.collect::<Vec<_>>()
.join(" ");
if note.is_empty() {
bail!("memory note is empty");
}
if note.len() > MAX_NOTE_BYTES {
bail!("memory note exceeds {MAX_NOTE_BYTES} bytes");
}
Ok(note.trim_start_matches('-').trim().to_string())
}View on GitHub (pinned to 433685b202)