astrid-runtime/astrid · error
gateway revocation namespace exceeds entry cap
Error message
gateway revocation namespace exceeds entry cap
What it means
Bounds guard in load_from_store: the number of principal/device revocation keys listed from the fixed control namespace exceeded the entry cap, so startup hydration aborts rather than trusting an oversized revocation set.
Solutions
- Audit the revocation namespace for runaway key growth (e.g. a bug writing unbounded keys)
- Prune expired/rotated revocation entries below the cap
- Raise the cap only after confirming the growth is legitimate
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at crates/astrid-gateway/src/revocations.rs:310 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/2529313cc6e1a644.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-gateway/src/revocations.rs:310
};
Ok(publish_device_epoch(revoked_key_ids, key_id, durable_epoch))
}
/// Load all durable principal and device epochs from the fixed control
/// namespace. Every key/value is bounded and validated before publication.
pub async fn load_from_store(
store: &dyn KvStore,
) -> anyhow::Result<(HashMap<PrincipalId, u64>, HashMap<String, u64>)> {
let principal_keys = store
.list_keys_with_prefix(REVOCATION_NAMESPACE, PRINCIPAL_PREFIX)
.await
.map_err(|error| anyhow::anyhow!("list principal revocations: {error}"))?;
let device_keys = store
.list_keys_with_prefix(REVOCATION_NAMESPACE, DEVICE_PREFIX)
.await
.map_err(|error| anyhow::anyhow!("list device revocations: {error}"))?;
if principal_keys.len().saturating_add(device_keys.len()) > MAX_REVOCATION_ENTRIES {
anyhow::bail!("gateway revocation namespace exceeds entry cap");
}
let mut principals = HashMap::with_capacity(principal_keys.len());
for key in principal_keys {
let alias = key
.strip_prefix(PRINCIPAL_PREFIX)
.filter(|alias| !alias.is_empty())
.ok_or_else(|| anyhow::anyhow!("invalid principal revocation key {key:?}"))?;
let principal = PrincipalId::new(alias).map_err(|error| {
anyhow::anyhow!("invalid principal revocation key {key:?}: {error}")
})?;
let value = store
.get(REVOCATION_NAMESPACE, &key)
.await
.map_err(|error| anyhow::anyhow!("read principal revocation {key:?}: {error}"))?
.ok_or_else(|| {
anyhow::anyhow!("principal revocation {key:?} disappeared during load")
})?;
principals.insert(principal, decode_epoch(&value, &key)?);View on GitHub (pinned to affd8760f4)