astrid-runtime/astrid · error
legacy gateway revocation path is not a regular file
Error message
legacy gateway revocation path is not a regular file: {} What it means
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.
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
Defensive patterns
Strategy: fallback
When it happens
Trigger: Thrown at crates/astrid-gateway/src/revocations.rs:62 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/7cd12d30bb84e3b2.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-gateway/src/revocations.rs:62
const MIGRATION_RECEIPT_KEY: &str = "migration/legacy-json-v1";
const MAX_REVOCATION_ENTRIES: usize = 1_000_000;
/// Released JSON file under `etc/`, retained only as a one-time migration
/// source. Runtime authority is the system control KV namespace above.
fn revocations_path() -> anyhow::Result<PathBuf> {
let home = astrid_core::dirs::AstridHome::resolve()
.map_err(|e| anyhow::anyhow!("resolve $ASTRID_HOME for revocation file: {e}"))?;
Ok(home.etc_dir().join("gateway-revocations.json"))
}
/// Whether the released JSON index exists. Used only to fail closed when a
/// standalone gateway has no authoritative KV wiring during startup.
pub fn legacy_file_exists() -> anyhow::Result<bool> {
let path = revocations_path()?;
match std::fs::symlink_metadata(&path) {
Ok(metadata) => {
if metadata.file_type().is_symlink() || !metadata.is_file() {
anyhow::bail!(
"legacy gateway revocation path is not a regular file: {}",
path.display()
);
}
Ok(true)
},
Err(error) if error.kind() == std::io::ErrorKind::NotFound => Ok(false),
Err(error) => Err(anyhow::anyhow!("inspect legacy revocation file: {error}")),
}
}
/// Hard cap on the legacy migration file. Each entry is ~50 bytes of JSON;
/// `10 MiB` gives migration ample room without permitting an unbounded boot
/// allocation from a corrupted or hostile operator file.
const MAX_REVOCATIONS_FILE_BYTES: u64 = 10 * 1024 * 1024;
fn read_legacy_bytes(path: &std::path::Path) -> anyhow::Result<Vec<u8>> {
#[cfg(unix)]View on GitHub (pinned to affd8760f4)