jdx/mise · error

workspace project ID

Error message

workspace project ID {value:?} must include a provider namespace

What it means

Workspace ProjectId parses strings of the form 'provider:local_id' via FromStr. If the value has no ':' separator, there is no provider namespace, and the parser bails — every project ID must name its provider (e.g. github:owner/repo).

Solutions

  1. Add the provider namespace: `github:owner/repo` instead of `owner/repo`
  2. Check the documented provider names and use the exact `provider:local-id` format
  3. Fix the config/lockfile entry that holds the bare ID
  4. If generating IDs programmatically, always join provider and local id with ':'

Example fix

// before
projects = ["owner/repo"]
// after
projects = ["github:owner/repo"]
Defensive patterns

Strategy: validation

Validate before calling

[[ "$PROJECT_ID" == *:* ]] || echo "project ID '$PROJECT_ID' needs a 'provider:local-id' form"

Try / catch

[[ "$PROJECT_ID" == *:* ]] || PROJECT_ID="github:$PROJECT_ID"; mise run build

Prevention

When it happens

Trigger: Parsing a workspace project ID string like `owner/repo` or `myproject` (no colon) into ProjectId::from_str, e.g. from config, lockfiles, or CLI args describing workspace members.

Common situations: Hand-editing workspace config and omitting the provider prefix; older configs written before namespacing was required; scripts passing bare repo slugs; typos dropping the 'github:'/'gitlab:' prefix.

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/5d13f07b8fde6018. Report an issue: GitHub.

Appendix: source

Thrown at src/task/workspace.rs:57

    /// Returns the serialized project ID.
    pub(crate) fn as_str(&self) -> &str {
        &self.0
    }
}

impl Display for ProjectId {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        Display::fmt(&self.0, f)
    }
}

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(())

View on GitHub (pinned to 533346cc37)