{"record":{"id":"947aa0f715362cac","repo":"astrid-runtime/astrid","slug":"destination-proof-is-missing-its-payload","errorCode":null,"errorMessage":"destination proof is missing its payload","messagePattern":"destination proof is missing its payload","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-kernel/src/legacy_migration_barrier/proof.rs","lineNumber":71,"sourceCode":"            || value.starts_with(\"verified-capsule-authority-v1:\")\n            || value.starts_with(\"verified-system-env-v1:\")\n            || value.starts_with(\"verified-secret-import-v1:\")\n            || value.starts_with(\"fresh-layout-v1:\");\n        if !known_prefix {\n            return Err(\"unknown destination proof prefix\");\n        }\n        let rest = value\n            .split_once(':')\n            .map(|(_, rest)| rest)\n            .unwrap_or_default();\n        if rest.is_empty() {\n            return Err(\"destination proof is missing its payload\");\n        }\n        Ok(Self(value))\n    }\n\n    pub(super) fn from_stored(value: impl Into<String>) -> io::Result<Self> {\n        Self::parse(value).map_err(|error| io::Error::new(io::ErrorKind::InvalidData, error))\n    }\n\n    pub(super) fn is_absent(&self) -> bool {\n        self.0 == Self::ABSENT\n    }\n}\n\nimpl std::fmt::Display for DestinationProof {\n    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        formatter.write_str(&self.0)\n    }\n}\n\nimpl AsRef<str> for DestinationProof {\n    fn as_ref(&self) -> &str {\n        &self.0\n    }\n}","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-kernel/src/legacy_migration_barrier/proof.rs#L53-L89","documentation":"A destination proof string in the component migration ledger used a known `verified-*` or `fresh-layout-v1:` prefix, but the payload after the first `:` was empty. `DestinationProof::parse` requires `prefix:payload` form; `from_stored` surfaces this as an InvalidData io::Error. The ledger's proof receipt is structurally malformed and cannot be trusted as evidence that a migration destination was verified.","triggerScenarios":"Calling `DestinationProof::from_stored` (directly or via ledger decode) on a stored proof value such as `\"verified-empty-v1:\"` with nothing after the colon. Caused by hand-editing the ledger JSON, truncated writes, or tooling that wrote the prefix without computing the proof payload.","commonSituations":"Manual ledger edits during debugging; a migration tool that crashed mid-write leaving a partial proof; third-party scripts rewriting `fresh-layout-v1:` receipts without their payload.","solutions":["Restore the full proof string including its payload (e.g. `verified-empty-v1:<digest-or-id>`) in the migration ledger.","Regenerate the ledger by re-running the migration/verification step that produced the destination proof.","If the ledger is unrecoverable, remove it and re-run the component import so fresh proofs are written.","Never construct proof strings by hand; use `DestinationProof::from_hashed_bytes` or the preset constructors."],"exampleFix":"// before\nlet proof = \"verified-empty-v1:\"; // missing payload\n// after\nlet proof = DestinationProof::from_hashed_bytes(&bytes).to_string();\n// e.g. \"blake3:<64 hex chars>\"","handlingStrategy":"validation","validationCode":"fn proof_looks_well_formed(s: &str) -> bool {\n    let Some((prefix, rest)) = s.split_once(':') else { return false };\n    rest.len() > 0 && (prefix == \"blake3\" || prefix.starts_with(\"verified-\") || prefix == \"fresh-layout-v1\")\n}\nassert!(proof_looks_well_formed(&stored_proof), \"ledger proof malformed\");","typeGuard":"fn has_proof_payload(p: &str) -> bool {\n    p.split_once(':').map(|(_, rest)| !rest.is_empty()).unwrap_or(false)\n}","tryCatchPattern":"match DestinationProof::from_stored(value) {\n    Ok(proof) => /* ... */,\n    Err(e) if e.kind() == std::io::ErrorKind::InvalidData => {\n        eprintln!(\"corrupt ledger proof ({e}); regenerate the migration ledger\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Never hand-edit migration ledger JSON; use the provided constructors.","Write the ledger atomically so partial proofs never persist.","Validate ledger contents after any external tooling touches it."],"tags":["validation","migration","ledger","corrupt-data"],"backgroundTag":"schema-validation-failed","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}