astrid-runtime/astrid · error
capsule name '{}' is invalid (must match ^[a-z][a-z0-9-]*$)
Error message
capsule name '{}' is invalid (must match ^[a-z][a-z0-9-]*$) What it means
Capsule names become filesystem path components in the `.shuttle` layout (`capsules/<name>.capsule`) and under the capsule store, so validate_manifest enforces the safe identifier pattern `^[a-z][a-z0-9-]*$`. This blocks `/`, `..`, uppercase, underscores, and other path-hostile or ambiguous characters from reaching the disk layout.
Source
Thrown at crates/astrid-cli/src/commands/distro/validate.rs:133
);
}
}
}
// At least one capsule.
if manifest.capsules.is_empty() {
anyhow::bail!("distro must contain at least one capsule");
}
// No duplicate capsule names, and each name must be a valid
// identifier. Names become path components in the `.shuttle` layout
// (`capsules/<name>.capsule`) and on disk under the capsule store;
// constraining them to `^[a-z][a-z0-9-]*$` keeps a manifest from
// introducing `/`, `..`, or other path-hostile characters there.
let mut seen_names = HashSet::new();
for cap in &manifest.capsules {
if !is_valid_id(&cap.name) {
anyhow::bail!(
"capsule name '{}' is invalid (must match ^[a-z][a-z0-9-]*$)",
cap.name,
);
}
if !seen_names.insert(&cap.name) {
anyhow::bail!("duplicate capsule name '{}'", cap.name);
}
// Distros compose *released* capsules. `branch`/`rev` selectors
// can only be honored by compiling from a git ref — the exact
// toolchain dependency offline/headless distro seeding exists to
// remove. Reject them: a distro must pin a released `version` or
// `tag`. (Git-ref installs remain available via the standalone
// `astrid capsule install` command.)
if cap.branch.is_some() || cap.rev.is_some() {
anyhow::bail!(
"capsule '{}': branch/rev require building from source and are not allowed in a \
distro manifest — pin a released `version` or `tag` (git-ref installs are \
available via `astrid capsule install`).",View on GitHub (pinned to affd8760f4)
Solutions
- Rename the capsule to lowercase letters/digits/hyphens starting with a letter (e.g. `my-lib`).
- Update all references to the old capsule name in requires/selectors.
- Re-run distro validation to confirm the new name passes.
Example fix
# before [[capsules]] name = "My_Lib/2" # after [[capsules]] name = "my-lib-2"
Defensive patterns
Strategy: validation
Validate before calling
fn is_valid_id(name: &str) -> bool {
let mut chars = name.chars();
matches!(chars.next(), Some(c) if c.is_ascii_lowercase())
&& chars.all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '-')
}
for cap in &manifest.capsules {
assert!(is_valid_id(&cap.name), "invalid capsule name: {}", cap.name);
} Type guard
fn is_valid_capsule_name(s: &str) -> bool {
!s.is_empty()
&& s.chars().next().is_some_and(|c| c.is_ascii_lowercase())
&& s.chars().all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '-')
} Try / catch
if let Err(e) = validate_manifest(&manifest) {
if e.to_string().contains("is invalid (must match") {
eprintln!("rename capsule: {e}");
}
} Prevention
- Stick to lowercase letters, digits, and hyphens; start with a letter
- Never embed paths, underscores, or uppercase in capsule names
- Validate names at manifest-generation time, not just at build time
When it happens
Trigger: A `[[capsules]]` entry whose `name` fails `is_valid_id`: starts with a digit or `-`, contains uppercase, `_`, `/`, `.`, `..`, spaces, or is empty.
Common situations: Naming a capsule after a GitHub repo (`My-Lib_v2`); pasting a path like `tools/http`; typos such as leading whitespace or a leading digit `2fa`.
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
- distro.id '{}' is invalid (must match ^[a-z][a-z0-9-]*$)
- distro.astrid-version '{av}' is not a valid semver requireme
- distro.requires.{ns}.{name} '{req}' is not a valid semver re
- distro must contain at least one capsule
- duplicate capsule name '{}'
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/0cdd2ec166d238a3.
Report an issue: GitHub.