jdx/mise · error
the packslip names an artifact {:?}, which is not a plain fi
Error message
the packslip names an artifact {:?}, which is not a plain file name What it means
Thrown by `install_payload` in the packslip backend when the manifest names an artifact whose `name` is not a plain file name (per `file::is_plain_file_name` — e.g. it contains path separators, `..`, or otherwise looks like a path). mise rejects such names before constructing the download path, preventing path traversal or unsafe file placement inside the install directory.
Source
Thrown at src/backend/packslip.rs:1235
let mut commands = BTreeMap::new();
if let Some(req) = &artifact.requires {
for bin in &req.bin {
// Spawnable, not merely present: the probe below runs the
// path with `--version`, so a shebang-only script or a `.ps1`
// would be chosen and then fail to start.
if let Some(path) = ctx.ts.which_bin_spawnable(&ctx.config, &bin.name).await {
commands.insert(bin.name.clone(), path);
}
}
}
crate::packslip_requirements::check(&artifact, &commands)
.await
.enforce(raw_opts.get("ignore_requirements") == Some("true"))?;
let Some(url) = artifact.url.clone() else {
bail!("the packslip gives no download URL for {}", artifact.name);
};
if !file::is_plain_file_name(&artifact.name) {
bail!(
"the packslip names an artifact {:?}, which is not a plain file name",
artifact.name
);
}
let file_path = tv.download_path().join(&artifact.name);
ctx.pr.next_operation();
ctx.pr.set_message(format!("download {}", artifact.name));
HTTP.download_file_with_headers(
&url,
&file_path,
&headers_for(&url)?,
Some(ctx.pr.as_ref()),
)
.await?;
// The signed digest and size first, then what the lockfile remembers:
// a lock entry written from an earlier packslip keeps its checksum and
// is compared, so a newly signed manifest cannot quietly replace whatView on GitHub (pinned to afd2eddd3a)
Solutions
- Upgrade or downgrade the tool version so the packslip manifest uses plain artifact file names (`mise use packslip:owner/repo@<version>`).
- Inspect the manifest's artifact names for your platform; if they embed paths, report the malformed packslip to the upstream project.
- Use an alternate backend with well-formed asset names (`mise use aqua:owner/repo` or `mise use github:owner/repo`).
- If you control the packslip generation, fix the publisher to emit bare file names for each artifact.
Example fix
// upstream packslip manifest artifact entry
// before
{ "name": "dist/mytool-linux-amd64.tar.gz", "url": "..." }
// after
{ "name": "mytool-linux-amd64.tar.gz", "url": "..." } Defensive patterns
Strategy: validation
Validate before calling
// reject artifact names with path separators before installing
const isPlain = name && !name.includes('/') && !name.includes('\\') && name !== '.' && name !== '..';
if (!isPlain) throw new Error(`artifact name ${name} is not a plain file name`); Type guard
function isPlainFileName(name) { return typeof name === 'string' && /^[^/\\]+$/u.test(name) && name !== '.' && name !== '..'; } Try / catch
try { await $`mise install` } catch (e) { if (String(e).includes('not a plain file name')) { /* switch backend or report upstream manifest */ } else throw e; } Prevention
- Audit packslip manifests for path-like artifact names
- Report upstream manifests embedding directory prefixes
- Use github/aqua backends as a safer fallback
When it happens
Trigger: Installing a packslip-backed tool where the manifest's artifact `name` for your platform contains characters like `/`, `\`, or leading directories (e.g. `"bin/tool.tar.gz"` or `"../tool"`) so `is_plain_file_name` returns false.
Common situations: An upstream project publishes signed manifests where artifact names include subpaths; a maliciously or accidentally crafted manifest; platform-specific artifacts named with directory prefixes; manifest format drift after a publisher tooling change.
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
Related errors
- the packslip gives no download URL for {}
- must not record a pin before replacement succeeds
- packslip:{project}@{version}: manifest digest differs from s
- the packslip names an executable {:?}, which is not a plain
- the packslip lists executable {} in {}, but the archive hold
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/c9138b6bc635b472.
Report an issue: GitHub.