{"record":{"id":"d703cd9dea54221e","repo":"astrid-runtime/astrid","slug":"invaliddata-d703cd","errorCode":"InvalidData","errorMessage":"invalid private-file write journal","messagePattern":"invalid private-file write journal","errorType":"error_code","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"crates/astrid-core/src/platform_fs/windows/private_file.rs","lineNumber":300,"sourceCode":"            .is_some_and(|name| !is_single_path_component(OsStr::new(name)))\n        || !journal.staged.contains(&journal.transaction_id)\n        || journal\n            .rollback\n            .as_deref()\n            .is_some_and(|name| !name.contains(&journal.transaction_id))\n        || journal\n            .legacy_displaced\n            .as_deref()\n            .is_some_and(|name| !name.contains(&journal.transaction_id))\n        || journal.had_live != journal.rollback.is_some()\n        || journal.had_live != journal.old_hash.is_some()\n        || !valid_digest(&journal.new_hash)\n        || journal\n            .old_hash\n            .as_deref()\n            .is_some_and(|hash| !valid_digest(hash))\n    {\n        return Err(io::Error::new(\n            io::ErrorKind::InvalidData,\n            \"invalid private-file write journal\",\n        ));\n    }\n    Ok(())\n}\n\npub(super) fn is_single_path_component(value: &OsStr) -> bool {\n    let mut components = Path::new(value).components();\n    matches!(components.next(), Some(Component::Normal(_))) && components.next().is_none()\n}\n\npub(super) fn finish_private_file_transaction(\n    parent: &Path,\n    journal: &PrivateFileTransaction,\n    guard: &TrustedPathGuard,\n) -> io::Result<()> {\n    guard","sourceCodeStart":282,"sourceCodeEnd":318,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-core/src/platform_fs/windows/private_file.rs#L282-L318","documentation":"When recovering, read_private_file_transaction_journal parses the journal JSON and then validate_private_file_transaction checks its integrity: version must be 1, the transaction id a 32-hex-char UUID, target/staged/rollback names single path components containing the id, had_live consistent with rollback/old_hash presence, and both digests 64 hex chars. Any violation means the journal is corrupt or tampered with, so recovery refuses with InvalidData.","triggerScenarios":"The journal file on disk was truncated, hand-edited, corrupted by a crash/partial flush, or written by an incompatible library version; the file passes JSON parsing but fails structural validation.","commonSituations":"Disk corruption or incomplete flush after power loss; a user manually edited/deleted parts of the journal; downgrading the library so an older/newer journal shape fails the deny_unknown_fields parse or version check.","solutions":["Inspect .astrid-private-write.transaction.json; if it is corrupt and no live data depends on it, remove the journal and its .astrid-private.* companion files so the next operation starts clean (this discards the pending transaction's rollback).","Verify the live target file's contents manually before deleting the journal; if the write actually completed, the data is intact and only the journal is stale.","Check library version consistency: journals written by other versions may fail validation; upgrade/downgrade to the version that wrote the journal to recover it properly."],"exampleFix":"// before: recovery keeps failing with InvalidData on a corrupt journal\n// after: manually clear the pending transaction after confirming the target file\nif std::fs::read(&state).map(|d| sha256(&d) == expected).unwrap_or(false) {\n    std::fs::remove_file(dir.join(\".astrid-private-write.transaction.json\")).ok();\n    atomic_write_private_file(&state, data)?;\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match result {\n    Err(e) if e.kind() == std::io::ErrorKind::InvalidData && e.to_string().contains(\"invalid private-file write journal\") => {\n        // journal corrupt: verify live file, remove journal + .astrid-private.* files, retry\n    }\n    other => other?,\n}","preventionTips":["Never hand-edit journal files.","Keep library versions consistent across writers.","Enable disk error monitoring (chkdsk/S.M.A.R.T.)."],"tags":["windows","crash-recovery","journal","data-integrity"],"backgroundTag":"checksum-mismatch","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}