Hmbown/CodeWhale · error · std::io::Error

(serde_json serialization error wrapped as…

Error message

(serde_json serialization error wrapped as io::ErrorKind::InvalidData)

What it means

While publishing the legacy spillover ownership sidecar, the LegacySpilloverOwnership struct is serialized to pretty JSON via serde_json::to_vec_pretty. If serialization fails, the error is wrapped as io::ErrorKind::InvalidData. This is rare for plain structs but possible (e.g. a map key or value type that serde cannot serialize), and it aborts the ownership write before anything is placed on disk.

Solutions

  1. Read the wrapped serde message to see which field failed to serialize.
  2. Verify LegacySpilloverOwnership fields are all plainly serializable types (strings, u64) after recent changes.
  3. Confirm serde_json is built with standard features and no custom serializers are in play.
  4. If it persists, capture the error in a unit test with the exact bytes/struct to pin down the failing field.

Example fix

// before
let encoded = serde_json::to_vec_pretty(&ownership)
    .map_err(|error| io::Error::new(io::ErrorKind::InvalidData, error))?;
// after (diagnostic)
let encoded = serde_json::to_vec_pretty(&ownership).unwrap_or_else(|error| {
    panic!("spillover ownership serialization failed: {error}") // invariant: plain struct
});
Defensive patterns

Strategy: try-catch

Try / catch

match publish_legacy_spillover_ownership(&path, &sid, &bytes) {
    Err(e) if e.kind() == std::io::ErrorKind::InvalidData => eprintln!("serialization failed: {e}"),
    other => other?,
}

Prevention

When it happens

Trigger: Calling publish_legacy_spillover_ownership where serde_json::to_vec_pretty(&ownership) fails — practically only when the struct contains non-serializable data (NaN floats, non-string map keys) or a poisoned custom serializer; the standard fields here make this an internal-invariant style failure.

Common situations: A modified LegacySpilloverOwnership struct gained a field whose type fails serialization at runtime; serde feature flags changed; corrupted in-memory digest/size data.

Understand the failure class

Background: "JSON serialization failed", "not JSON serializable", "Failed to serialize": why JSON marshaling errors happen and how to fix them — this error's family across 46 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/c95b3a8cfa4784e6. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/tools/truncate.rs:153

    payload_path: &Path,
    session_id: &str,
    bytes: &[u8],
) -> io::Result<PathBuf> {
    if session_id.trim().is_empty() {
        return Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            "legacy spillover ownership requires a session id",
        ));
    }
    let ownership = LegacySpilloverOwnership {
        schema_version: LEGACY_SPILLOVER_OWNER_SCHEMA_VERSION,
        origin_session: session_id.to_string(),
        digest: crate::hashing::sha256_hex(bytes),
        size_bytes: bytes.len().try_into().unwrap_or(u64::MAX),
    };
    let sidecar = legacy_spillover_ownership_path(payload_path);
    let encoded = serde_json::to_vec_pretty(&ownership)
        .map_err(|error| io::Error::new(io::ErrorKind::InvalidData, error))?;
    crate::utils::write_atomic(&sidecar, &encoded)?;
    Ok(sidecar)
}

pub(crate) fn read_legacy_spillover_ownership(
    payload_path: &Path,
) -> io::Result<LegacySpilloverOwnership> {
    let sidecar = legacy_spillover_ownership_path(payload_path);
    if std::fs::symlink_metadata(&sidecar)?
        .file_type()
        .is_symlink()
    {
        return Err(io::Error::new(
            io::ErrorKind::PermissionDenied,
            "legacy spillover ownership sidecar must not be a symlink",
        ));
    }
    let ownership = serde_json::from_slice::<LegacySpilloverOwnership>(&std::fs::read(sidecar)?)

View on GitHub (pinned to 433685b202)