tonhowtf/omniget · error · std::io::Error

e.to_string()

Error message

e.to_string()

What it means

Inside save_state, serde_json::to_string_pretty serializes AnonymousCookieState; if serialization fails the anyhow/std error is converted into an io::Error with ErrorKind::InvalidData and message e.to_string() (the serde error text, e.g. "failed to serialize..." — AnonymousCookieState derives Serialize so this is rare). The message is dynamic, hence the placeholder name.

Solutions

  1. Inspect the inner serde message (the error text) to find which field failed serialization.
  2. Audit AnonymousCookieState fields for custom Serialize impls or non-string map keys and fix them.
  3. Keep the struct simple (String/u64/i64 fields) so to_string_pretty cannot fail.
  4. Consider using a typed error (serde_json::Error) instead of flattening into io::Error for better diagnostics.

Example fix

// before
let serialized = serde_json::to_string_pretty(state)
    .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e.to_string()))?;

// after
let serialized = serde_json::to_string_pretty(state)
    .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, format!("serialize AnonymousCookieState: {e}")))?;
Defensive patterns

Strategy: try-catch

Try / catch

match save_state(&state) {
    Err(e) if e.kind() == std::io::ErrorKind::InvalidData => {
        tracing::error!("anonymous state serialization failed: {e}");
    }
    r => r?,
}

Prevention

When it happens

Trigger: bootstrap_anonymous → save_state with an AnonymousCookieState that serde cannot serialize — practically only possible if a non-serializable value (e.g. a map with non-string keys or a poisoned custom Serialize impl) is present, or if the struct gains a field with a failing custom serializer.

Common situations: After a code change adds a field whose Serialize impl errors; misuse of serde_json::Value containing invalid data injected into the state; version mismatch between omniget-core crates sharing the struct.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12). Data as JSON: /api/errors/fcc552348b4f9779. Report an issue: GitHub.

Appendix: source

Thrown at src-tauri/src/platforms/bilibili/cookie.rs:73

        Some(p) => p,
        None => return AnonymousCookieState::default(),
    };
    let content = match std::fs::read_to_string(&path) {
        Ok(c) => c,
        Err(_) => return AnonymousCookieState::default(),
    };
    serde_json::from_str(&content).unwrap_or_default()
}

pub fn save_state(state: &AnonymousCookieState) -> std::io::Result<()> {
    let path = meta_file_path().ok_or_else(|| {
        std::io::Error::new(std::io::ErrorKind::Other, "app_data_dir unavailable")
    })?;
    if let Some(parent) = path.parent() {
        std::fs::create_dir_all(parent)?;
    }
    let serialized = serde_json::to_string_pretty(state)
        .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e.to_string()))?;
    std::fs::write(path, serialized)
}

pub async fn ensure_fresh() -> Result<AnonymousCookieState> {
    let cached = load_state();
    if cached.is_fresh() {
        write_netscape_for_anonymous(&cached).ok();
        return Ok(cached);
    }
    bootstrap_anonymous().await
}

pub async fn bootstrap_anonymous() -> Result<AnonymousCookieState> {
    let ua = super::api::DEFAULT_USER_AGENT;
    let now_ms = now_ms();
    let uuid = gen_uuid_b_lsid();
    let b_lsid = gen_b_lsid();
    let b_nut = now_ms.to_string();

View on GitHub (pinned to 8600b91f42)