zeroclaw-labs/zeroclaw · error

skills.extra_registries[{i}].name '{}' is invalid; use only

Error message

skills.extra_registries[{i}].name '{}' is invalid; use only lowercase ASCII letters, numbers, '-' or '_' so it can be addressed as registry:<name>/<skill>

What it means

ExternalRegistry::is_valid_name gates registry names to lowercase ASCII letters, digits, '-' and '_' only; Config::validate() bails for anything else. The constraint exists because the name is embedded in skill addresses of the form registry:<name>/<skill> and must round-trip through the skill-resolution grammar without quoting; uppercase, spaces, dots, or ':' would make the address ambiguous or unparseable.

Source

Thrown at crates/zeroclaw-config/src/schema.rs:21972

                && !std::path::Path::new(tpl_dir).exists()
            {
                anyhow::bail!("project_intel.templates_dir path does not exist: {tpl_dir}");
            }
        }

        // Proxy (delegate to existing validation)
        self.proxy.validate()?;
        self.cloud_ops.validate()?;

        // Skills — extra registries
        {
            let mut seen = std::collections::HashSet::new();
            for (i, reg) in self.skills.extra_registries.iter().enumerate() {
                if reg.name.trim().is_empty() {
                    anyhow::bail!("skills.extra_registries[{i}].name must not be empty");
                }
                if !ExternalRegistry::is_valid_name(&reg.name) {
                    anyhow::bail!(
                        "skills.extra_registries[{i}].name '{}' is invalid; use only lowercase ASCII letters, numbers, '-' or '_' so it can be addressed as registry:<name>/<skill>",
                        reg.name
                    );
                }
                if !seen.insert(reg.name.as_str()) {
                    anyhow::bail!("skills.extra_registries has duplicate name '{}'", reg.name);
                }
                if reg.url.trim().is_empty() {
                    anyhow::bail!(
                        "skills.extra_registries[{}].url must not be empty",
                        reg.name
                    );
                }
                if reg.kind != ExternalRegistryKind::Git {
                    anyhow::bail!(
                        "skills.extra_registries[{}].kind must be 'git' (got '{}'); other protocols are not yet supported",
                        reg.name,
                        reg.kind

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Rewrite the name as a lowercase slug using only a-z, 0-9, '-', '_' (e.g. "team-skills")
  2. Keep it stable: renaming later changes every registry:<name>/<skill> reference
  3. Add a separate display/description field elsewhere if a pretty label is needed

Example fix

# before
[[skills.extra_registries]]
name = "Team Skills"
url = "https://git.example.com/team/skills.git"

# after
[[skills.extra_registries]]
name = "team-skills"
url = "https://git.example.com/team/skills.git"
Defensive patterns

Strategy: type-guard

Validate before calling

for reg in &cfg.skills.extra_registries {
    if !ExternalRegistry::is_valid_name(&reg.name) { /* reject early */ }
}

Type guard

// Mirrors ExternalRegistry::is_valid_name: registry:<name>/<skill> must stay parseable
fn is_valid_registry_name(name: &str) -> bool {
    !name.is_empty()
        && name
            .chars()
            .all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '-' || c == '_')
}

Try / catch

match config.validate() {
    Ok(()) => {}
    Err(e) if e.to_string().contains("name '") && e.to_string().contains("is invalid") => {
        // slugify the name: lowercase, spaces/dots -> '-'
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: A registry entry with name = "My Registry", name = "Team.Skills", or name = "org/registry" failing ExternalRegistry::is_valid_name during Config::validate().

Common situations: Using a human-friendly display name instead of a slug; copying an org/team name with spaces from a Git host; national characters or smart quotes pasted from documentation.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/bcff4cde718eb727. Report an issue: GitHub.