jdx/mise · error
Nix package references must not contain control characters
Error message
Nix package references must not contain control characters
What it means
`Installable::parse` validates every Nix package reference before it is passed to a `nix` command. Nix arguments are joined into shell-ish command lines and interpolated into `nix eval --expr` strings, so control characters (newlines, tabs, NUL, etc.) are rejected outright — they are never valid in a flake or attribute name and would corrupt or inject into the constructed expression.
Solutions
- Inspect the package name in your config and remove the control character; re-type the name on a single line.
- Trim/normalize generated config output before writing package names.
- Add a lint step that rejects control characters in package names.
- If a template or script emits package lists, validate with something like `name.chars().all(|c| !c.is_control())` before applying.
Example fix
# before (folded string contains a newline) packages = ["rip\ grep"] # after packages = ["ripgrep"]
Defensive patterns
Strategy: validation
Validate before calling
fn valid_pkg_name(name: &str) -> bool {
!name.is_empty() && !name.chars().any(char::is_control)
}
assert!(valid_pkg_name(pkg)); Type guard
fn is_plain_str(s: &str) -> bool { s.chars().all(|c| !c.is_control()) } Prevention
- Avoid multi-line folded strings for package names in TOML/YAML
- Trim script/generated output before writing config
- Lint package names for control characters in CI
When it happens
Trigger: A package name in config contains a control character (e.g. an accidental newline from YAML/TOML line folding, a tab, or an escape sequence) and reaches `Installable::parse`, called from `install`, `upgrade`, and `matching_entries`.
Common situations: Multi-line TOML/YAML strings that silently fold a newline into the package name; generated configs from scripts that don't trim output; copy-paste from terminals introducing invisible characters.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- invalid Nix flake reference
- invalid Nix package attribute
- a repository preview directory requires a dry run
- action prediction payload is too large
- agent ' ' `start_calendar_interval. ` must be between and
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/69fd41d502108123.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/packages/nix.rs:26
use serde_json::Value;
use super::{InstallOpts, PackageRequest, PackageState, PackageStatus, SystemPackageManager};
pub(crate) struct NixManager;
/// Bootstrap accepts attribute paths and explicit flake references, not Nix
/// expressions, store paths, or output selectors. Nix owns source resolution.
#[derive(Debug)]
pub(crate) struct Installable<'a> {
pub source: &'a str,
pub attribute: &'a str,
pub explicit: bool,
}
impl<'a> Installable<'a> {
pub(crate) fn parse(name: &'a str) -> Result<Self> {
if name.chars().any(char::is_control) {
bail!("Nix package references must not contain control characters");
}
let (source, attribute, explicit) = match name.split_once('#') {
Some((source, attribute)) => {
if source.is_empty()
|| source.starts_with('-')
|| source.starts_with('.')
|| source.starts_with('/')
|| source
.strip_prefix("path:")
.is_some_and(|p| !p.starts_with('/'))
{
bail!(
"invalid Nix flake reference '{source}'; use a registry name, URL, or path:/absolute/path"
);
}
(source, attribute, true)
}
None => ("nixpkgs", name, false),View on GitHub (pinned to 533346cc37)