{"record":{"id":"930892138c8c560e","repo":"jdx/mise","slug":"artifactbundle-asset-must-end-with-artifactbundle","errorCode":null,"errorMessage":"artifactbundle_asset must end with .artifactbundle.zip, got {name}","messagePattern":"artifactbundle_asset must end with \\.artifactbundle\\.zip, got (.+?)","errorType":"validation","errorClass":"eyre::Report","httpStatus":null,"severity":"error","filePath":"src/backend/spm.rs","lineNumber":924,"sourceCode":"                        })\n                        .collect()\n                })\n        }\n    };\n    let Some(assets) = assets else {\n        return Ok(None);\n    };\n    select_artifactbundle_asset(assets, opts)\n}\n\nfn select_artifactbundle_asset(\n    assets: Vec<ArtifactBundleReleaseAsset>,\n    opts: &SpmOptions<'_>,\n) -> eyre::Result<Option<ArtifactBundleReleaseAsset>> {\n    let artifactbundle_asset = opts.artifactbundle_asset(None);\n    if let Some(name) = artifactbundle_asset {\n        if !is_artifactbundle_zip(&name) {\n            bail!(\"artifactbundle_asset must end with .artifactbundle.zip, got {name}\");\n        }\n        return assets\n            .into_iter()\n            .find(|a| a.name == name)\n            .map(Some)\n            .ok_or_else(|| {\n                eyre::eyre!(\"artifactbundle_asset not found in release assets: {name}\")\n            });\n    }\n\n    let candidates = assets\n        .into_iter()\n        .filter(|a| is_artifactbundle_zip(&a.name))\n        .collect::<Vec<_>>();\n    match candidates.len() {\n        0 => Ok(None),\n        1 => Ok(candidates.into_iter().next()),\n        _ => bail!(","sourceCodeStart":906,"sourceCodeEnd":942,"githubUrl":"https://github.com/jdx/mise/blob/6f52dcdf99e282ef7a7db68c81301fa4618d0f79/src/backend/spm.rs#L906-L942","documentation":"When a spm tool pins `artifactbundle_asset`, the asset name must end with `.artifactbundle.zip` (checked case-insensitively elsewhere). This error means the configured name fails that suffix check, so mise rejects the selection before looking at the release.","triggerScenarios":"`artifactbundle_asset = \"Repo-1.0.0.tar.gz\"`, `\"Repo.artifactbundle.tar.gz\"`, or `\"Repo.artifactbundle\"` — anything not ending in .artifactbundle.zip.","commonSituations":"Guessing the asset name instead of copying it from the GitHub release page, or targeting a plain zip the project publishes alongside its bundles.","solutions":["Copy the exact asset filename from the release; it must end with .artifactbundle.zip","If the release only has a plain tarball/zip, that asset cannot be used as a bundle — remove artifactbundle_asset and use source build or another backend","Check for trailing spaces or wrong extension when hand-typing the name"],"exampleFix":"# before\n[tools.\"spm:foo/bar\"]\nversion = \"1.0.0\"\nartifactbundle_asset = \"Bar-macos.artifactbundle\"\n\n# after\n[tools.\"spm:foo/bar\"]\nversion = \"1.0.0\"\nartifactbundle_asset = \"Bar-macos.artifactbundle.zip\"","handlingStrategy":"validation","validationCode":"name='Bar-macos.artifactbundle.zip'; case \"${name,,}\" in *.artifactbundle.zip) echo ok;; *) echo 'must end with .artifactbundle.zip';; esac","typeGuard":"fn is_artifactbundle_zip(name: &str) -> bool { name.to_lowercase().ends_with(\".artifactbundle.zip\") }","tryCatchPattern":null,"preventionTips":["Copy asset names verbatim from the GitHub release page","Only .artifactbundle.zip assets are bundles; plain zips need a different mechanism"],"tags":["spm","swift","config-validation","release-assets","mise-toml"],"backgroundTag":"config-validation-failed","analyzedSha":"6f52dcdf99e282ef7a7db68c81301fa4618d0f79","analyzedAt":"2026-08-22T10:14:23.840Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}