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
- Fix the manifest/release so every asset carries a real file name
- Re-fetch the release info before downloading if the manifest may have changed
- 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
- Validate asset names with safe_asset_name at manifest-ingest time, not at download time
- Fail manifest generation when the artifact filename variable is empty
- Re-fetch the manifest if it may have been regenerated since the last check
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
- 没有可下载的 Release asset
- CDP WebSocket URL must include an explicit port
- Responses 请求体不是 UTF-8:{error}
- openai/plugins marketplace download is too large: {} bytes
- downloaded openai/plugins marketplace is invalid
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@1f431ae49b (2026-08-16).
Data as JSON: /api/errors/301c7b08215be52c.
Report an issue: GitHub.