jdx/mise · error

mas install requires a numeric ADAM ID ('{p}'); use `mas sea

Error message

mas install requires a numeric ADAM ID ('{p}'); use `mas search` to find it

What it means

mas identifies apps by numeric Apple ADAM IDs, not names. Before shelling out, install() validates every package name with is_adam_id and rejects non-numeric names with this error pointing the user at `mas search`.

Source

Thrown at src/system/packages/mas.rs:260

    async fn unavailable_reason_async(&self) -> Option<String> {
        self.bin().await.err().map(|err| format!("{err:#}"))
    }

    fn supports_version_pins(&self) -> bool {
        false
    }

    async fn installed(&self, pkgs: &[PackageRequest]) -> Result<Vec<PackageStatus>> {
        let apps = mas_list(self.bin().await?).await?;
        Ok(statuses_from_apps(&apps, pkgs))
    }

    async fn install(&self, pkgs: &[PackageRequest], opts: &InstallOpts) -> Result<()> {
        if let Some(p) = pkgs.iter().find(|p| p.version.is_some()) {
            bail!("mas cannot install a pinned version ('{p}')");
        }
        if let Some(p) = pkgs.iter().find(|p| !is_adam_id(&p.name)) {
            bail!("mas install requires a numeric ADAM ID ('{p}'); use `mas search` to find it");
        }
        let mut args = vec!["install".to_string()];
        args.extend(pkgs.iter().map(|p| p.name.clone()));
        if opts.dry_run {
            miseprintln!("mas {}", args.join(" "));
            return Ok(());
        }
        debug!("$ mas {}", args.join(" "));
        let output = tokio::process::Command::new(self.bin().await?)
            .args(&args)
            .stdin(Stdio::null())
            .output()
            .await?;
        if !output.status.success() {
            let stderr = String::from_utf8_lossy(&output.stderr);
            bail!("mas install failed: {}", stderr.trim());
        }
        Ok(())

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Find the numeric ID with `mas search <app name>` and use it as the package name
  2. Use only digits in the package name (e.g. 497799835 for Xcode)
  3. If constructing requests programmatically, validate with the is_adam_id check before calling install

Example fix

// before
PackageRequest { name: "Xcode".into(), .. }
// after
PackageRequest { name: "497799835".into(), .. }
Defensive patterns

Strategy: validation

Validate before calling

fn is_adam_id(name: &str) -> bool { !name.is_empty() && name.chars().all(|c| c.is_ascii_digit()) }

Type guard

fn as_adam_id(name: &str) -> Option<&str> {
    (!name.is_empty() && name.chars().all(|c| c.is_ascii_digit())).then_some(name)
}

Try / catch

match provider.install(&pkgs, &opts).await {
    Err(e) if e.to_string().contains("numeric ADAM ID") => {
        eprintln!("resolve names with `mas search <name>` and retry");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling mas install with a PackageRequest whose name is not a numeric ADAM ID — e.g. `mas install Xcode`, a human-readable app name, or a name with stray characters/spaces.

Common situations: Users copying app names from the App Store instead of IDs; configs migrated from Homebrew casks (`mas: xcode`); typos such as a leading letter or embedded whitespace in the ID.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/ff28292c6592d8c9. Report an issue: GitHub.