astrid-runtime/astrid · error
keypair name contains invalid chars; only a-z, 0-9, '-' are…
Error message
keypair name {name:?} contains invalid chars; only a-z, 0-9, '-' are allowed What it means
validate_name rejects keypair names containing characters outside lowercase ASCII letters, digits, and '-'. This mirrors principal-id formatting and prevents path-separator or shell-metacharacter surprises when the name is used in file paths.
Solutions
- Rename the keypair using only a-z, 0-9, and '-' (e.g. "my_key" -> "my-key")
- Check for accidental whitespace or invisible characters (trim the input)
- Replace '.' or '_' separators with '-'
Example fix
// before
run_show("My_Key.prod")?
// after
run_show("my-key-prod")? Defensive patterns
Strategy: validation
Validate before calling
fn valid_keypair_name(name: &str) -> bool {
!name.is_empty()
&& name.chars().all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '-')
} Type guard
fn is_slug(name: &str) -> bool { !name.is_empty() && name.chars().all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '-') } Try / catch
match run_show(&name) {
Err(e) if e.to_string().contains("invalid chars") => eprintln!("use only a-z, 0-9, '-'"),
other => other,
} Prevention
- Use slug-style names (a-z, 0-9, '-') by convention
- Trim inputs to avoid stray spaces
- Avoid '_', '.', uppercase, and path characters in names
When it happens
Trigger: Any keypair command (generate/show/pubkey/delete) or a public-key load / binding record where the name contains uppercase letters, underscores, spaces, dots, slashes, or other non-allowed characters.
Common situations: Using snake_case names like "my_key"; CamelCase names; names copied with a trailing space; names containing dots or '/'.
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
- capsule name ' ' is invalid (must match ^[a-z][a-z0-9-]*$)
- keypair name must be at most
- byte value must be non-negative and finite
- capsule ' ': branch/rev require building from source and…
- capsule ' ': tag must not be empty
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/e34cdf7f810c12af.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-cli/src/commands/keypair.rs:591
// ── Misc helpers ─────────────────────────────────────────────────
fn validate_name(name: &str) -> Result<()> {
if name.is_empty() {
bail!("keypair name must not be empty");
}
if name.len() > MAX_NAME_LEN {
bail!(
"keypair name must be at most {MAX_NAME_LEN} chars (got {})",
name.len()
);
}
// Lowercase letters, digits, dash. Same posture as principal ids;
// also avoids path-separator / shell-meta surprises.
if !name
.chars()
.all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '-')
{
bail!("keypair name {name:?} contains invalid chars; only a-z, 0-9, '-' are allowed");
}
Ok(())
}
fn default_name() -> String {
let mut bytes = [0u8; 4];
SysRng
.try_fill_bytes(&mut bytes)
.expect("OS CSPRNG unavailable while generating default keypair name");
format!("key-{}", hex::encode(bytes))
}
fn fingerprint_pubkey(hex_pub: &str) -> Result<String> {
PublicKeyFingerprint::from_ed25519_hex(hex_pub)
.map(PublicKeyFingerprint::into_inner)
.map_err(|e| anyhow::anyhow!("fingerprint Ed25519 public key: {e}"))
}
View on GitHub (pinned to affd8760f4)