{"record":{"id":"e58786a8e0f73b63","repo":"Hmbown/CodeWhale","slug":"continual-harness-entry-id-cannot-be-empty","errorCode":null,"errorMessage":"continual harness entry id cannot be empty","messagePattern":"continual harness entry id cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/continual_harness.rs","lineNumber":138,"sourceCode":"            content: refinement.content,\n            evidence: refinement.evidence,\n        };\n        state.schema_version = SCHEMA_VERSION;\n        state.entries.push(entry.clone());\n        save_state(&path, &state)?;\n        // Journalled after the state is durable: a logged edit that never\n        // landed would be worse than an unlogged one.\n        append_journal(&path, \"refine\", &entry)?;\n        Ok(entry)\n    })\n}\n\n/// Remove one exact entry. Returning the removed entry makes deletion\n/// receipts useful without re-reading the state file.\npub fn remove(workspace: &Path, id: &str) -> Result<HarnessEntry> {\n    let id = id.trim();\n    if id.is_empty() {\n        bail!(\"continual harness entry id cannot be empty\");\n    }\n    let path = state_path_for_write(workspace)?;\n    with_write_lock(&path, || {\n        let mut state = load_state(&path)?;\n        let index = state\n            .entries\n            .iter()\n            .position(|entry| entry.id == id)\n            .ok_or_else(|| anyhow!(\"continual harness has no entry `{id}`\"))?;\n        let removed = state.entries.remove(index);\n        state.schema_version = SCHEMA_VERSION;\n        save_state(&path, &state)?;\n        // Removal is the edit most worth recording: the entry is gone from\n        // state, so the journal is the only place its content survives.\n        append_journal(&path, \"remove\", &removed)?;\n        Ok(removed)\n    })\n}","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/continual_harness.rs#L120-L156","documentation":"Argument guard in continual_harness remove(): the caller-supplied entry id must be a non-empty string (after trimming) before the harness state is read and journalled. It fires on remove(\"\") or remove(\"   \") — no state mutation happens.","triggerScenarios":"Calling harness::remove(workspace, \"\") or with a whitespace-only id.","commonSituations":"A script with an unset id variable; a UI passing through an empty selection.","solutions":["Pass the actual entry id (the h_<uuid> value returned by refine/list).","Validate the id is non-empty before calling remove."],"exampleFix":"// before\nharness::remove(ws, \"\")?;\n// after\nanyhow::ensure!(!id.trim().is_empty(), \"id required\");\nharness::remove(ws, id)?;","handlingStrategy":"validation","validationCode":"let id = id.trim();\nif id.is_empty() { return Err(anyhow::anyhow!(\"entry id required\")); }","typeGuard":"fn has_entry_id(id: &str) -> bool { !id.trim().is_empty() }","tryCatchPattern":"match harness::remove(ws, id) {\n    Err(e) if e.to_string().contains(\"id cannot be empty\") => report_missing_id(),\n    other => other,\n}","preventionTips":["Carry the h_<uuid> id returned by refine/list rather than reconstructing it.","Validate ids before invoking removal in scripts.","Handle unset env/CLI id variables explicitly."],"tags":["validation","empty-value","continual-harness"],"backgroundTag":"empty-required-field","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}