unicity-aos/aos-ce · warning

failed to deserialize IPC message payload

Error message

failed to deserialize IPC message payload: {e}

What it means

Each IPC message carries a JSON string payload. dispatch_poll_result deserializes it with serde_json; when parsing fails (malformed JSON, empty string, binary data), the capsule logs this warning and skips the message via continue. The library throws it to prevent one corrupt message from aborting the whole poll dispatch.

Solutions

  1. Fix the producing capsule to serialize payloads with serde_json::to_string instead of manual string building.
  2. Log msg.topic and a payload prefix alongside the error to identify the offending publisher, then repair it.
  3. Validate payload shape on the producer side before publishing (round-trip serialize/deserialize in tests).
  4. If the payload is intentionally non-JSON, switch the message to an encoding the bus contract defines (e.g. base64-wrapped JSON).

Example fix

// before: building payload by hand
let payload = format!("{key}={value}");
bus.publish(topic, payload);
// after: proper JSON serialization
let payload = serde_json::to_string(&serde_json::json!({ "key": key, "value": value }))?;
bus.publish(topic, payload);
Defensive patterns

Strategy: validation

Validate before calling

// guard before dispatching a message
fn is_valid_json(s: &str) -> bool { serde_json::from_str::<serde_json::Value>(s).is_ok() }
if !is_valid_json(&msg.payload) { skip(msg); }

Type guard

fn as_json(payload: &str) -> Option<serde_json::Value> {
    serde_json::from_str(payload).ok()
}

Prevention

When it happens

Trigger: dispatch_poll_result encounters a queued message whose msg.payload is not valid JSON — e.g. a publisher wrote a non-UTF8-safe string, truncated payload, or raw bytes serialized as a string.

Common situations: A publisher capsule serializing with a different/older schema writes invalid JSON; truncated IPC frames under backpressure; hand-crafted test messages pasted into the bus; payloads built via string concatenation instead of a serializer.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


AI-assisted analysis of unicity-aos/aos-ce@f6f22024fb (2026-09-13). Data as JSON: /api/errors/f3c9f496e1678510. Report an issue: GitHub.

Appendix: source

Thrown at capsules/capsule-context-engine/src/lib.rs:342

/// Dispatch messages from a typed `PollResult`.
fn dispatch_poll_result(result: &ipc::PollResult, config: &Config) {
    if result.dropped > 0 {
        log::warn(format!(
            "Event bus dropped {} messages in context engine poll",
            result.dropped
        ));
    }

    for msg in &result.messages {
        if !should_dispatch_topic(&msg.topic) {
            continue;
        }

        let payload: serde_json::Value = match serde_json::from_str(&msg.payload) {
            Ok(v) => v,
            Err(e) => {
                log::warn(format!("failed to deserialize IPC message payload: {e}"));
                continue;
            }
        };

        // Extract from Custom payload envelope or direct.
        let request_value = payload.get("data").unwrap_or(&payload);

        match msg.topic.as_str() {
            "context_engine.v1.compact" => handle_compact(request_value, config),
            "context_engine.v1.estimate_tokens" => handle_estimate_tokens(request_value),
            _ => {}
        }
    }
}

// ── Compact handler ─────────────────────────────────────────────────

/// Handle a `context_engine.v1.compact` request.

View on GitHub (pinned to f6f22024fb)