{"record":{"id":"cd810624e69b9f55","repo":"jdx/mise","slug":"packslip-artifact-must-declare-extensions-mise-plu","errorCode":null,"errorMessage":"packslip artifact must declare extensions.mise.plugin = vfox","messagePattern":"packslip artifact must declare extensions\\.mise\\.plugin = vfox","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/plugins/packslip.rs","lineNumber":177,"sourceCode":"    }\n    if let Err(error) = file::rename(payload, destination) {\n        if existed {\n            file::rename(backup, destination).wrap_err(\"restoring previous plugin\")?;\n        }\n        return Err(error);\n    }\n    if let Err(error) = commit() {\n        file::rename(destination, payload)?;\n        if existed {\n            file::rename(backup, destination).wrap_err(\"restoring previous plugin\")?;\n        }\n        return Err(error);\n    }\n    Ok(())\n}\n\npub(crate) fn validate_artifact(artifact: &packslip::model::Artifact) -> Result<()> {\n    ensure!(\n        artifact\n            .extensions\n            .get(\"mise\")\n            .and_then(|v| v.get(\"plugin\"))\n            .and_then(|v| v.as_str())\n            == Some(\"vfox\"),\n        \"packslip artifact must declare extensions.mise.plugin = vfox\"\n    );\n    ensure!(\n        artifact.bin.is_empty(),\n        \"vfox plugin artifacts must not declare executables\"\n    );\n    ensure!(\n        artifact.os.is_none() && artifact.arch.is_none() && artifact.libc.is_none(),\n        \"vfox plugin artifact must be portable\"\n    );\n    ensure!(\n        artifact.requires.is_none(),","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/plugins/packslip.rs#L159-L195","documentation":"`validate_artifact` in src/plugins/packslip.rs enforces that a packslip artifact used as a vfox plugin declares `extensions.mise.plugin = \"vfox\"` in its release manifest. This marks the artifact as a plugin payload so mise treats it as vfox plugin code rather than an ordinary binary release. A manifest missing or mis-typing that key fails validation.","triggerScenarios":"Publishing/installing via `plugin_artifact_contract` where the artifact's `extensions` map lacks a `mise` object, lacks a `plugin` key, or has a non-string/`non-\"vfox\"` value — e.g. a manifest generated for a regular binary tool being consumed as a plugin.","commonSituations":"Plugin author forgot to add the extensions block to the release manifest; a template generated plain tool manifests; the key was renamed or quoted with a different value (e.g. \"vfox-plugin\").","solutions":["Add `extensions.mise.plugin = \"vfox\"` to the artifact's manifest and republish the release manifest.","Ensure the value is exactly the string \"vfox\" (not null, number, or another name).","If the artifact is actually a regular binary tool, install it via the normal packslip tool source rather than the plugin path."],"exampleFix":"// before (manifest)\n[artifacts.plugin]\nformat = \"tar.gz\"\n\n// after (manifest)\n[artifacts.plugin.extensions.mise]\nplugin = \"vfox\"\nformat = \"tar.gz\"","handlingStrategy":"validation","validationCode":"// pre-check manifest before publishing\njq -e '.artifacts[] | select(.extensions.mise.plugin == \"vfox\")' manifest.json \\\n  || { echo \"missing extensions.mise.plugin = vfox\"; exit 1; }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use a manifest template that always emits [artifacts.*.extensions.mise] plugin = \"vfox\" for plugin releases.","Validate manifests in CI with a JSON-schema/TOML check before cutting a release.","Keep plugin and binary tool manifests in separate templates."],"tags":["packslip","vfox","manifest","validation"],"backgroundTag":"missing-required-config-field","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}