xai-org/x-algorithm · error · anyhow::Error

failed to serialize ServedHistory: {e}

Error message

failed to serialize ServedHistory: {e}

What it means

Raised in put when xai_x_thrift::serialize_compact fails to serialize the ServedHistory struct into compact Thrift bytes before writing to Manhattan. This is a data-shape problem: the struct cannot be encoded, so nothing is written.

Source

Thrown at home-mixer/clients/served_history_client.rs:165

                }
            }
        }

        Ok(entries)
    }

    async fn put(
        &self,
        user_id: u64,
        timeline_type: TimelineType,
        client_platform: i32,
        served_time_ms: i64,
        history: &ServedHistory,
    ) -> Result<()> {
        let pkey = timeline_pkey(timeline_type, user_id, client_platform);
        let lkey = vec![(i64::MAX - served_time_ms).to_be_bytes().to_vec()];
        let value = xai_x_thrift::serialize_compact(history)
            .map_err(|e| anyhow::anyhow!("failed to serialize ServedHistory: {e}"))?;

        self.client
            .put(self.tenant.clone(), pkey, lkey, value)
            .await
            .map_err(|e| anyhow::anyhow!("MH put failed: {e}"))
    }

    async fn delete(
        &self,
        user_id: u64,
        timeline_type: TimelineType,
        client_platform: i32,
        served_times_ms: &[i64],
    ) -> Result<()> {
        let pkey = timeline_pkey(timeline_type, user_id, client_platform);
        for &ts in served_times_ms {
            let lkey = vec![(i64::MAX - ts).to_be_bytes().to_vec()];
            self.client

View on GitHub (pinned to 24c60942c5)

Solutions

  1. Log and inspect the exact ServedHistory values that fail to serialize; look for newly added or invalid fields
  2. Pin/align the xai-x-thrift crate version with the ServedHistory schema version
  3. Add a unit test that round-trips serialize_compact/deserialize_compact for representative ServedHistory values
  4. Reject/normalize invalid fields upstream before constructing ServedHistory

Example fix

// before
let value = xai_x_thrift::serialize_compact(history)
    .map_err(|e| anyhow::anyhow!("failed to serialize ServedHistory: {e}"))?;

// after
let value = xai_x_thrift::serialize_compact(history)
    .map_err(|e| {
        tracing::error!(error = ?e, history = ?history, "ServedHistory serialization failed");
        anyhow::anyhow!("failed to serialize ServedHistory: {e}")
    })?;
Defensive patterns

Strategy: validation

Validate before calling

fn valid_served_history(h: &ServedHistory) -> bool { /* check invariants: known enum values, valid utf-8, non-negative where required */ true }

Type guard

fn is_serializable(h: &ServedHistory) -> bool { xai_x_thrift::serialize_compact(h).is_ok() }

Try / catch

// Fail fast at construction; serialization errors are deterministic and non-retryable

Prevention

When it happens

Trigger: Calling put() with a ServedHistory containing fields the compact Thrift writer cannot encode (e.g. malformed nested enums, invalid UTF-8, or a schema/struct definition mismatch between writer and thrift definitions).

Common situations: Schema evolution where a new field type isn't supported by serialize_compact; corrupt/inconsistent struct invariants; version skew between the xai-x-thrift crate and the ServedHistory definition.

Related errors


AI-assisted analysis of xai-org/x-algorithm@24c60942c5 (2026-08-28). Data as JSON: /api/errors/810e7c8c366c3fef. Report an issue: GitHub.