unicity-aos/aos-ce · error
ingress pending read error for source_id
Error message
ingress pending read error for source_id '{source_id}', failing closed: {e} What it means
The MCP broker's take_ingress_pending looks up pending ingress state for a source_id in KV. If the read errors (as opposed to returning Ok(None)), the broker fails closed — treating the pending state as absent/denying continuation — and logs this warning prefixed with the broker's log tag.
Solutions
- Check the {e} detail and restore KV availability; retry the execute flow once the store is healthy.
- Delete the corrupted pending record for that source_id so the next read is a clean miss.
- Verify the stored pending value matches the current broker schema (version upgrade drift).
- Expect fail-closed behavior: callers will see the flow as not-pending; re-initiate the ingress flow.
Example fix
// before
Err(e) => {
log::warn(format!("{}: ingress pending read error for source_id '{source_id}', \
failing closed: {e}", crate::profile::log_tag()));
false
}
// after
// fix KV backend, or clear the bad key:
kv::delete(&pending_key(source_id)).ok();
Err(e) => {
log::warn(format!("{}: ingress pending read error for source_id '{source_id}', \
failing closed: {e}", crate::profile::log_tag()));
false
} Defensive patterns
Strategy: try-catch
Validate before calling
// before relying on pending state, probe the store
const reachable = await kv.ping();
if (!reachable) throw new Error('kv unavailable, execute flow will fail closed'); Try / catch
match kv::get(&pending_key) {
Ok(Some(v)) => resume(v),
Ok(None) => /* not pending */ false,
Err(e) => { log::warn("ingress pending read error: {e}"); false } // fail closed
} Prevention
- Monitor KV availability during MCP execute flows
- Version pending records to survive broker upgrades
- Clear corrupt pending keys instead of retrying reads
When it happens
Trigger: KV read of the ingress-pending entry for source_id returns Err inside take_ingress_pending — storage backend unavailable, decode failure of the stored value, or an I/O error on the pending record.
Common situations: KV store restart or network partition during an MCP execute flow; corrupted/unexpected bytes at the pending key after a schema change; source_id reused across broker restarts with stale records.
Understand the failure class
Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.
Related errors
- grant pending read error for capsule_id
- aos-mcp: could not retire
- aos-mcp: could not audit rejected hook message
- capability check failed for
- grant pending read error for capsule_id
AI-assisted analysis of unicity-aos/aos-ce@f6f22024fb (2026-09-13).
Data as JSON: /api/errors/be0740d532a83390.
Report an issue: GitHub.
Appendix: source
Thrown at crates/aos-mcp-broker/src/execute.rs:420
/// is one re-usable stale marker, never a denied legitimate grant).
pub(crate) fn take_ingress_pending(source_id: &str) -> bool {
let Some(key) = ingress_pending_key(source_id) else {
return false;
};
match kv::get_bytes_opt(&key) {
Ok(Some(_)) => {
if let Err(e) = kv::delete(&key) {
log::warn(format!(
"{}: failed to clear ingress pending marker for source_id \
'{source_id}': {e}",
crate::profile::log_tag()
));
}
true
}
Ok(None) => false,
Err(e) => {
log::warn(format!(
"{}: ingress pending read error for source_id '{source_id}', \
failing closed: {e}",
crate::profile::log_tag()
));
false
}
}
}
/// KV key marking an outstanding capsule-grant consent prompt for a
/// `(principal, capsule_id)` pair. KV is per-principal-scoped by the kernel,
/// so the capsule id alone disambiguates within the keyspace — the principal
/// is implicit in the storage scope, not the key suffix. Same empty-suffix
/// guard as [`ingress_pending_key`]: an empty `capsule_id` must never resolve
/// to a routable key (it would collapse to the bare prefix and let one marker
/// dedup every grant prompt for the principal). The `principal` is accepted
/// for symmetry with the call sites and to keep the dedup key intent explicit,
/// but is NOT stamped into the suffix (the KV scope already carries it).View on GitHub (pinned to f6f22024fb)