unicity-aos/aos-ce · warning
Dropped ingress message: connection bound to
Error message
Dropped ingress message: connection bound to {bound:?} but message claimed {claimed:?} What it means
decide_ingress returned Drop with DropReason::PrincipalConflict: the message's claimed principal does not match the principal already bound to this connection. The library drops the message and returns an empty outcome, keeping the original binding intact — this prevents an authenticated connection from being hijacked by sending messages claiming a different identity.
Solutions
- Compare the logged {bound:?} vs {claimed:?} to see which identity mismatched and fix the client to send messages under its bound principal
- Have the client open a new connection instead of reusing one bound to a different principal
- If the principal legitimately changed, close and re-establish the connection so it rebinds
- Audit connection pooling/multiplexing code for socket sharing across identities
Example fix
// before conn.send(msg_claiming(other_principal)) // conflicts with bound principal // after let conn = Connection::connect_as(my_principal)?; conn.send(msg);
Defensive patterns
Strategy: validation
Validate before calling
if let Some(bound) = conn.bound_principal() {
assert_eq!(bound, &msg.principal, "message principal must match bound connection principal");
} Type guard
fn principal_matches(conn: &Connection, claimed: &Principal) -> bool {
conn.bound_principal().map_or(false, |b| b == *claimed)
} Prevention
- Always send messages on a connection under the principal it was bound with
- Reconnect with the new principal after credential rotation instead of reusing the socket
- Avoid sharing connections across processes or identities
- Treat principal-conflict warnings as possible connection-pooling bugs
When it happens
Trigger: A client reuses an already-bound connection and sends a message whose principal differs from the one bound at IngressDecision::Bind; decide_ingress returns Drop { reason: PrincipalConflict { bound, claimed } } and handle_ingress logs this warning.
Common situations: Connection pooling bugs where one client's socket is handed to another process; a client restarted with different credentials but kept the old socket; load balancers multiplexing sessions onto one connection; credentials rotated mid-session.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Dropped ingress message: malformed principal
- Dropped ingress message to blocked topic
- hook-adapter-oracle: dropping mismatched context reply on
- Unicity AOS health service must bind to 127.0.0.1
- product manifest path must be a regular file
AI-assisted analysis of unicity-aos/aos-ce@f6f22024fb (2026-09-13).
Data as JSON: /api/errors/ea8e0b245e6b9d14.
Report an issue: GitHub.
Appendix: source
Thrown at capsules/capsule-cli/src/lib.rs:570
Err(_) => {
log::warn("Received malformed IPC payload from socket");
return empty;
}
};
let message_principal = msg.get("principal").and_then(|p| p.as_str());
// Resolve the binding decision first — a conflicting or malformed
// principal is dropped before any forward, and never mutates the binding.
let (forward_as, newly_bound) = match decide_ingress(current_binding, message_principal) {
IngressDecision::Bind(p) => (p.clone(), Some(p)),
IngressDecision::ForwardAs(p) => (p, None),
IngressDecision::Drop { reason } => {
match reason {
DropReason::InvalidPrincipal(p) => log::warn(format!(
"Dropped ingress message: malformed principal {p:?}; connection stays unbound"
)),
DropReason::PrincipalConflict { bound, claimed } => log::warn(format!(
"Dropped ingress message: connection bound to {bound:?} but message claimed {claimed:?}"
)),
}
return empty;
}
};
let (Some(topic), Some(payload)) = (
msg.get("topic").and_then(|t| t.as_str()),
msg.get("payload"),
) else {
// No forwardable body, but the principal still binds the connection
// (e.g. a bare handshake establishes identity for connect-tracking).
// Nothing is forwarded, so the connection's session is never retargeted.
log::warn("Ingress message has no topic/payload; binding only, nothing forwarded");
return IngressOutcome {
newly_bound,
session_id: None,View on GitHub (pinned to f6f22024fb)