jdx/mise · error

invalid bootstrap secret name

Error message

invalid bootstrap secret name '{name}': use ASCII letters, digits, '.', '_' or '-'

What it means

Bootstrap secret names are used as keys in config and possibly in external stores, so mise validates them against a strict charset: ASCII letters, digits, '.', '_' and '-'. An empty name or one containing other characters is rejected at parse time.

Solutions

  1. Rename the secret key in the config to only ASCII letters, digits, '.', '_' or '-'
  2. Check for empty or malformed table headers in the [bootstrap.secrets] section
  3. If the secret must map to a differently-named backend key, keep the config name simple and put the complex name in the env/target field

Example fix

# before
[bootstrap.secrets."auth/token"]
env = "AUTH_TOKEN"
# after
[bootstrap.secrets.auth_token]
env = "AUTH_TOKEN"
Defensive patterns

Strategy: validation

Validate before calling

fn valid_secret_name(name: &str) -> bool {
    !name.is_empty()
        && name.chars().all(|c| c.is_ascii_alphanumeric() || "_.-".contains(c))
}
// run over all keys under [bootstrap.secrets] before loading config

Type guard

fn is_valid_secret_key(key: &toml::Value) -> bool {
    key.as_str().map(valid_secret_name).unwrap_or(false)
}

Prevention

When it happens

Trigger: declaration_from_toml is invoked from secrets_from_config_files while parsing a [bootstrap.secrets.*] table whose key is empty or contains spaces, slashes, unicode, or symbols outside the allowed set.

Common situations: Writing a secret key with a space ("MY KEY"), using a path-like name ("auth/token"), or accidentally leaving an empty table header [bootstrap.secrets."] after an edit.

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

Appendix: source

Thrown at src/system/secrets.rs:427

        None if prompt => prompt_value(declaration).map_err(|error| error.to_string())?,
        None => return Err(format!("{} ({})", declaration.name, declaration.env)),
    };
    if value.is_empty() && !declaration.allow_empty {
        return Err(format!(
            "{} ({}) must not be empty",
            declaration.name, declaration.env
        ));
    }
    Ok(value)
}

fn declaration_from_toml(name: String, declaration: SecretTomlConfig) -> Result<SecretDeclaration> {
    if name.is_empty()
        || !name
            .chars()
            .all(|character| character.is_ascii_alphanumeric() || "_.-".contains(character))
    {
        bail!("invalid bootstrap secret name '{name}': use ASCII letters, digits, '.', '_' or '-'");
    }
    let (env, description, allow_empty) = match declaration {
        SecretTomlConfig::Env(env) => (env, None, false),
        SecretTomlConfig::Options(options) => {
            (options.env, options.description, options.allow_empty)
        }
    };
    if !valid_env_name(&env) {
        bail!("bootstrap secret '{name}' has invalid environment variable name '{env}'");
    }
    Ok(SecretDeclaration {
        name,
        env,
        description,
        allow_empty,
    })
}

View on GitHub (pinned to 533346cc37)