BigPizzaV3/CodexPlusPlus · error · anyhow::Error

非法 Release asset 文件名: {name}

Error message

非法 Release asset 文件名: {name}

What it means

safe_asset_name is the path-safety gate for release asset file names; its first check rejects names that are empty or only whitespace ("非法 Release asset 文件名: {name}"). download_asset_to calls it before joining the name onto download_dir, so a blank name can never cause a write to the directory itself. select_update_asset already filters empty names upstream, so hitting this usually means download_asset_to/safe_asset_name was called directly or the payload changed between selection and download.

Source

Thrown at crates/codex-plus-core/src/update.rs:331

pub fn download_asset_to(
    release: &Release,
    bytes: &[u8],
    download_dir: &Path,
) -> anyhow::Result<PathBuf> {
    let name = release
        .asset_name
        .as_ref()
        .ok_or_else(|| anyhow::anyhow!("没有可下载的 Release asset"))?;
    let safe = safe_asset_name(name)?;
    std::fs::create_dir_all(download_dir)?;
    let path = download_dir.join(safe);
    std::fs::write(&path, bytes)?;
    Ok(path)
}

pub fn safe_asset_name(name: &str) -> anyhow::Result<String> {
    if name.trim().is_empty() {
        anyhow::bail!("非法 Release asset 文件名: {name}");
    }
    let path = Path::new(name);
    if path.components().count() != 1 {
        anyhow::bail!("非法 Release asset 文件名: {name}");
    }
    let file_name = path
        .file_name()
        .and_then(|name| name.to_str())
        .ok_or_else(|| anyhow::anyhow!("非法 Release asset 文件名: {name}"))?;
    if file_name == "." || file_name == ".." {
        anyhow::bail!("非法 Release asset 文件名: {name}");
    }
    Ok(file_name.to_string())
}

fn platform_asset_rank(name: &str) -> u8 {
    // 0 = exact match (current OS + native arch)
    // 1 = same OS, other arch (acceptable fallback, e.g. x86_64 on arm64 or vice versa)

View on GitHub (pinned to 1f431ae49b)

Solutions

  1. Fix the manifest/release so every asset carries a real file name
  2. Re-fetch the release info before downloading if the manifest may have changed
  3. Pre-validate with the public safe_asset_name() before calling download_asset_to

Example fix

// before
let path = download_asset_to(&release, &bytes, &dir)?;

// after
if let Some(name) = release.asset_name.as_deref() {
    safe_asset_name(name)?; // fail fast with the real cause
}
let path = download_asset_to(&release, &bytes, &dir)?;
Defensive patterns

Strategy: validation

Validate before calling

if let Some(name) = release.asset_name.as_deref() {
    codex_plus_core::update::safe_asset_name(name)?; // rejects blank names up front
}

Prevention

When it happens

Trigger: download_asset_to with release.asset_name = Some("") or Some(" "); direct calls to safe_asset_name("") in tests or custom pipelines; a manifest whose asset name field is present but blank.

Common situations: Hand-edited latest.json with "name": ""; a generator emitting an empty name when the artifact filename variable is unset; the manifest being regenerated between the update check and the download.

Related errors


AI-assisted analysis of BigPizzaV3/CodexPlusPlus@1f431ae49b (2026-08-16). Data as JSON: /api/errors/301c7b08215be52c. Report an issue: GitHub.