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

app_data_dir unavailable

Error message

app_data_dir unavailable

What it means

save_state persists the anonymous Bilibili cookie state as JSON. It resolves the metadata file path via meta_file_path(), which returns None when the app data directory cannot be resolved; the function then raises an io::Error with message "app_data_dir unavailable". Without a writable data dir, anonymous cookie state cannot be persisted.

Solutions

  1. Run the app in an environment where HOME (or the OS equivalent) is set and writable.
  2. Ensure save_state is only called after Tauri app setup so the path resolver is available.
  3. Add a fallback path (e.g. std::env::temp_dir or explicit config) when meta_file_path() returns None.
  4. Log the underlying reason in meta_file_path and surface it in the error message for diagnosis.

Example fix

// before
let path = meta_file_path().ok_or_else(|| {
    std::io::Error::new(std::io::ErrorKind::Other, "app_data_dir unavailable")
})?;

// after
let path = meta_file_path().or_else(|| {
    std::env::var_os("HOME").map(|h| std::path::PathBuf::from(h).join(".local/share/omniget/bilibili-anonymous.json"))
}).ok_or_else(|| {
    std::io::Error::new(std::io::ErrorKind::Other, "app_data_dir unavailable: HOME not set")
})?;
Defensive patterns

Strategy: fallback

Validate before calling

// Rust
if meta_file_path().is_none() {
    tracing::warn!("app_data_dir unavailable; anonymous cookie state will not persist");
}

Try / catch

match save_state(&state) {
    Err(e) if e.to_string().contains("app_data_dir unavailable") => {
        tracing::warn!("skipping anonymous state persistence: {e}");
    }
    r => r?,
}

Prevention

When it happens

Trigger: bootstrap_anonymous → save_state runs while meta_file_path() returns None because tauri/dirs cannot resolve the platform app-data directory (no HOME on Linux, sandboxed environment, path resolver not initialized).

Common situations: Headless CI or Docker runs without HOME/XDG_DATA_HOME; portable/flatpak builds with restricted data dirs; calling save_state before the Tauri app setup has run; corrupted user session environment.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


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

Appendix: source

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

            .join("_anonymous_meta.json"),
    )
}

pub fn load_state() -> AnonymousCookieState {
    let path = match meta_file_path() {
        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
}

View on GitHub (pinned to 8600b91f42)