zeroclaw-labs/zeroclaw · warning

Invalid Uno Q SSH user: use only ASCII letters, digits, '.',

Error message

Invalid Uno Q SSH user: use only ASCII letters, digits, '.', '_', or '-' and do not begin with '-'

What it means

After splitting, the SSH user part (explicit, or the 'arduino' default) is checked by valid_ssh_user: non-empty, must not start with '-', and every byte must be an ASCII letter, digit, '.', '_' or '-'. This bail rejects users containing spaces, shell metacharacters, non-ASCII characters, or a leading dash — option-like values that ssh/scp could misparse.

Source

Thrown at crates/zeroclaw-hardware/src/peripherals/uno_q_setup.rs:96

    println!("  transport = \"bridge\"");
    Ok(())
}

fn validated_ssh_target(value: &str) -> Result<String> {
    let mut parts = value.split('@');
    let first = parts.next().unwrap_or_default();
    let second = parts.next();
    if parts.next().is_some() {
        anyhow::bail!("Uno Q host must contain at most one '@'");
    }

    let (user, host) = match second {
        Some(host) => (first, host),
        None => ("arduino", first),
    };

    if !valid_ssh_user(user) {
        anyhow::bail!(
            "Invalid Uno Q SSH user: use only ASCII letters, digits, '.', '_', or '-' and do not begin with '-'"
        );
    }
    if !valid_ssh_host(host) {
        anyhow::bail!(
            "Invalid Uno Q host: use a DNS hostname or IPv4 address without SSH/SCP syntax characters"
        );
    }

    Ok(format!("{user}@{host}"))
}

fn valid_ssh_user(user: &str) -> bool {
    !user.is_empty()
        && !user.starts_with('-')
        && user
            .bytes()
            .all(|byte| byte.is_ascii_alphanumeric() || matches!(byte, b'.' | b'_' | b'-'))

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Use a plain ASCII username: letters, digits, and '.', '_', '-' only, not starting with '-'
  2. Pass ssh options via ~/.ssh/config instead of the host string
  3. For exotic usernames, create an SSH config Host alias with the right User and pass the alias as the host

Example fix

# before
setup_uno_q_bridge(Some("my user@uno-q.local"))

# after
# ~/.ssh/config:
#   Host unoq
#     HostName uno-q.local
#     User my_user
setup_uno_q_bridge(Some("unoq"))
Defensive patterns

Strategy: type-guard

Validate before calling

let user = host.split('@').next().unwrap_or("");
if !is_valid_ssh_user(user) {
    anyhow::bail!("invalid SSH user {user:?}: ASCII letters/digits/./_/- only, no leading '-'");
}
setup_uno_q_bridge(Some(host))?;

Type guard

fn is_valid_ssh_user(user: &str) -> bool {
    !user.is_empty()
        && !user.starts_with('-')
        && user.bytes().all(|b| b.is_ascii_alphanumeric() || matches!(b, b'.' | b'_' | b'-'))
}

Prevention

When it happens

Trigger: Passing 'user name@host' (space), '-user@host' or '-oProxyCommand=...@host' (leading '-'), 'usér@host' (non-ASCII), or an empty user as in '@host'.

Common situations: Pasting usernames with whitespace; trying to pass ssh options through the user field; internationalized system usernames.

Related errors


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