{"record":{"id":"7cd12d30bb84e3b2","repo":"astrid-runtime/astrid","slug":"legacy-gateway-revocation-path-is-not-a-regular-fi","errorCode":null,"errorMessage":"legacy gateway revocation path is not a regular file: {}","messagePattern":"legacy gateway revocation path is not a regular file: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-gateway/src/revocations.rs","lineNumber":62,"sourceCode":"const MIGRATION_RECEIPT_KEY: &str = \"migration/legacy-json-v1\";\nconst MAX_REVOCATION_ENTRIES: usize = 1_000_000;\n\n/// Released JSON file under `etc/`, retained only as a one-time migration\n/// source. Runtime authority is the system control KV namespace above.\nfn revocations_path() -> anyhow::Result<PathBuf> {\n    let home = astrid_core::dirs::AstridHome::resolve()\n        .map_err(|e| anyhow::anyhow!(\"resolve $ASTRID_HOME for revocation file: {e}\"))?;\n    Ok(home.etc_dir().join(\"gateway-revocations.json\"))\n}\n\n/// Whether the released JSON index exists. Used only to fail closed when a\n/// standalone gateway has no authoritative KV wiring during startup.\npub fn legacy_file_exists() -> anyhow::Result<bool> {\n    let path = revocations_path()?;\n    match std::fs::symlink_metadata(&path) {\n        Ok(metadata) => {\n            if metadata.file_type().is_symlink() || !metadata.is_file() {\n                anyhow::bail!(\n                    \"legacy gateway revocation path is not a regular file: {}\",\n                    path.display()\n                );\n            }\n            Ok(true)\n        },\n        Err(error) if error.kind() == std::io::ErrorKind::NotFound => Ok(false),\n        Err(error) => Err(anyhow::anyhow!(\"inspect legacy revocation file: {error}\")),\n    }\n}\n\n/// Hard cap on the legacy migration file. Each entry is ~50 bytes of JSON;\n/// `10 MiB` gives migration ample room without permitting an unbounded boot\n/// allocation from a corrupted or hostile operator file.\nconst MAX_REVOCATIONS_FILE_BYTES: u64 = 10 * 1024 * 1024;\n\nfn read_legacy_bytes(path: &std::path::Path) -> anyhow::Result<Vec<u8>> {\n    #[cfg(unix)]","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-gateway/src/revocations.rs#L44-L80","documentation":"Fail-closed check in the legacy revocation-file path helper: the path at etc/gateway-revocations.json exists but is a symlink or not a regular file, so the one-time migration source cannot be trusted and startup refuses to read it.","triggerScenarios":"Thrown at crates/astrid-gateway/src/revocations.rs:62 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Replace the symlink/irregular path with a real regular JSON file, or delete it if migration already happened","Check what created the symlink (provisioning script) and fix it","Ensure the migration receipt exists in the control KV so the legacy file is no longer needed"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"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"}