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
- Find the numeric ID with `mas search <app name>` and use it as the package name
- Use only digits in the package name (e.g. 497799835 for Xcode)
- 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
- Resolve human-readable names to IDs with `mas search` at authoring time
- Store ADAM IDs, not app names, in package configs
- Validate numeric-only names before submitting requests
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
- mas app IDs must be numeric ADAM IDs (e.g. "mas:497799835")
- mas upgrade requires a numeric ADAM ID ('{p}'); use `mas sea
- mas list --json returned an app object without an ID and ver
- mas list failed: {}
- mas install failed: {}
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/ff28292c6592d8c9.
Report an issue: GitHub.