{"record":{"id":"0deb5d947ae6c513","repo":"Hmbown/CodeWhale","slug":"continual-harness-state-has-no-parent","errorCode":null,"errorMessage":"continual harness state has no parent: {}","messagePattern":"continual harness state has no parent: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/continual_harness.rs","lineNumber":279,"sourceCode":"            path.display(),\n            state.schema_version,\n            SCHEMA_VERSION\n        );\n    }\n    if state.entries.len() > MAX_ENTRIES {\n        bail!(\n            \"continual harness state {} has {} entries; maximum is {MAX_ENTRIES}\",\n            path.display(),\n            state.entries.len()\n        );\n    }\n    Ok(state)\n}\n\nfn save_state(path: &Path, state: &HarnessState) -> Result<()> {\n    let parent = path\n        .parent()\n        .ok_or_else(|| anyhow!(\"continual harness state has no parent: {}\", path.display()))?;\n    fs::create_dir_all(parent)\n        .with_context(|| format!(\"create continual harness directory {}\", parent.display()))?;\n    let payload = serde_json::to_vec_pretty(state)?;\n    let tmp = path.with_extension(format!(\"{}.tmp\", Uuid::new_v4().simple()));\n    fs::write(&tmp, payload)\n        .with_context(|| format!(\"write continual harness temporary state {}\", tmp.display()))?;\n    if let Err(error) = fs::rename(&tmp, path) {\n        let _ = fs::remove_file(&tmp);\n        return Err(error).with_context(|| {\n            format!(\n                \"publish continual harness state {} -> {}\",\n                tmp.display(),\n                path.display()\n            )\n        });\n    }\n    Ok(())\n}","sourceCodeStart":261,"sourceCodeEnd":297,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/crates/tui/src/continual_harness.rs#L261-L297","documentation":"save_state persists the harness state atomically: it needs the state file's parent directory to create it and to place the UUID-named temp file next to the target. Path::parent returns None only for pathological paths (bare file name with no directory component), so this error indicates the caller passed a relative bare filename instead of a path with a directory component.","triggerScenarios":"Calling refine or remove with a state path that has no parent directory component, e.g. passing 'state.json' instead of './state.json' or an absolute path.","commonSituations":"Constructing the path from a bare filename constant; environment/config supplying a filename without a directory; tests passing \"state.json\" directly.","solutions":["Pass a path that includes a directory, e.g. PathBuf::from(\"./state.json\") or an absolute path via std::env::current_dir().join(file).","Normalize the path with std::fs::canonicalize (or join with the cwd) before handing it to the harness.","Fix the config/CLI argument that supplies the state path so it is not a bare filename."],"exampleFix":"// before\nlet path = Path::new(\"state.json\");\nharness.refine(&path, ...)?; // no parent\n// after\nlet path = std::env::current_dir()?.join(\"state.json\");\nharness.refine(&path, ...)?;","handlingStrategy":"validation","validationCode":"fn absolute_state_path(raw: &str) -> std::path::PathBuf {\n    let p = std::path::Path::new(raw);\n    if p.parent().map_or(true, |p| p.as_os_str().is_empty()) {\n        std::env::current_dir().unwrap_or_default().join(p)\n    } else {\n        p.to_path_buf()\n    }\n}","typeGuard":null,"tryCatchPattern":"match result {\n    Err(e) if e.to_string().contains(\"has no parent\") => {\n        eprintln!(\"state path must include a directory, e.g. ./state.json\");\n    }\n    other => other?,\n}","preventionTips":["Always pass absolute or at least directory-qualified state paths.","Resolve configured paths against the working directory or a data dir at startup.","Canonicalize user-supplied paths before handing them to persistence APIs."],"tags":["filesystem","path","state-persistence"],"backgroundTag":"invalid-argument-value","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}