jdx/mise · error

workspace ID contains surrounding whitespace or control…

Error message

workspace {kind} ID {value:?} contains surrounding whitespace or control characters

What it means

`validate_id_part` rejects workspace ID components that have leading/trailing whitespace or contain control characters. IDs are used in maps, prefixes like `provider:local`, and output, so untrimmed or invisible characters would break matching and lookups. The library rejects them up front with the offending value quoted.

Solutions

  1. Trim the ID before passing it (`.trim()`)
  2. Fix the config file to remove stray spaces or control characters
  3. Normalize line endings (CRLF -> LF) in files the ID is parsed from

Example fix

// before
let project = WorkspaceProject::new(provider, &raw_id);
// after
let project = WorkspaceProject::new(provider, raw_id.trim());
Defensive patterns

Strategy: validation

Validate before calling

let p = provider.trim();
let l = local_id.trim();
if p != provider || l != local_id {
    eprintln!("trimming workspace ID parts");
}
WorkspaceProject::new(p, l)?;

Type guard

fn is_clean_id(s: &str) -> bool { s.trim() == s && !s.chars().any(char::is_control) }

Try / catch

match WorkspaceProject::new(provider, local_id) {
    Ok(p) => p,
    Err(e) if e.to_string().contains("surrounding whitespace") => WorkspaceProject::new(provider.trim(), local_id.trim())?,
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling `new` or a provider's `collect_provider_projects` with IDs containing spaces at the edges (e.g. `" api "`) or control chars such as `\t`, `\n`, `\r` from untrimmed config values or split output.

Common situations: Hand-edited mise.toml with stray spaces after `=`; splitting provider metadata on a separator that leaves `\r` (CRLF files); shell-interpolated values with trailing whitespace.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/0f3bbb833b1ea3a4. Report an issue: GitHub.

Appendix: source

Thrown at src/task/workspace.rs:68

}

impl FromStr for ProjectId {
    type Err = eyre::Report;

    fn from_str(value: &str) -> Result<Self> {
        let Some((provider, local_id)) = value.split_once(':') else {
            bail!("workspace project ID {value:?} must include a provider namespace");
        };
        Self::new(provider, local_id)
    }
}

fn validate_id_part(kind: &str, value: &str) -> Result<()> {
    if value.is_empty() {
        bail!("workspace {kind} ID cannot be empty");
    }
    if value.trim() != value || value.chars().any(char::is_control) {
        bail!(
            "workspace {kind} ID {value:?} contains surrounding whitespace or control characters"
        );
    }
    if kind == "provider" && value.contains(':') {
        bail!("workspace provider ID {value:?} cannot contain ':'");
    }
    Ok(())
}

/// A project discovered from ecosystem-specific workspace metadata.
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
pub(crate) struct WorkspaceProject {
    /// Stable identity used by dependency edges and task scoping.
    pub id: ProjectId,
    /// Normalized path relative to the workspace root. `.` represents the root.
    pub root: PathBuf,
    /// Provider-neutral facts that consumers may use for inspection or inference.
    pub metadata: BTreeMap<String, String>,

View on GitHub (pinned to 533346cc37)