{"record":{"id":"977a77cd2cec2a26","repo":"zeroclaw-labs/zeroclaw","slug":"invalid-uno-q-host-use-a-dns-hostname-or-ipv4-add","errorCode":null,"errorMessage":"Invalid Uno Q host: use a DNS hostname or IPv4 address without SSH/SCP syntax characters","messagePattern":"Invalid Uno Q host: use a DNS hostname or IPv4 address without SSH/SCP syntax characters","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/zeroclaw-hardware/src/peripherals/uno_q_setup.rs","lineNumber":101,"sourceCode":"    let mut parts = value.split('@');\n    let first = parts.next().unwrap_or_default();\n    let second = parts.next();\n    if parts.next().is_some() {\n        anyhow::bail!(\"Uno Q host must contain at most one '@'\");\n    }\n\n    let (user, host) = match second {\n        Some(host) => (first, host),\n        None => (\"arduino\", first),\n    };\n\n    if !valid_ssh_user(user) {\n        anyhow::bail!(\n            \"Invalid Uno Q SSH user: use only ASCII letters, digits, '.', '_', or '-' and do not begin with '-'\"\n        );\n    }\n    if !valid_ssh_host(host) {\n        anyhow::bail!(\n            \"Invalid Uno Q host: use a DNS hostname or IPv4 address without SSH/SCP syntax characters\"\n        );\n    }\n\n    Ok(format!(\"{user}@{host}\"))\n}\n\nfn valid_ssh_user(user: &str) -> bool {\n    !user.is_empty()\n        && !user.starts_with('-')\n        && user\n            .bytes()\n            .all(|byte| byte.is_ascii_alphanumeric() || matches!(byte, b'.' | b'_' | b'-'))\n}\n\nfn valid_ssh_host(host: &str) -> bool {\n    !host.is_empty()\n        && host.split('.').all(|label| {","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-hardware/src/peripherals/uno_q_setup.rs#L83-L119","documentation":"The host part is checked by valid_ssh_host: non-empty, and every dot-separated label must start and end with an alphanumeric and contain only alphanumerics or '-' — i.e. a DNS hostname or IPv4 address. The message calls out the key exclusion: no SSH/SCP syntax characters. Colons (ports, IPv6), slashes (remote paths), brackets, '%', leftover '@', and empty labels ('host..example') all fail.","triggerScenarios":"Passing 'host:22' (port), 'user@host:/path' (scp destination), 'ssh://host', '[::1]' or 'fe80::1%eth0' (IPv6/zones), 'host..example' (empty label), or '-host' (label starts with a dash).","commonSituations":"Pasting scp-style targets or URLs; IPv6 link-local addresses; muscle memory from tools that accept host:port syntax.","solutions":["Pass only a bare hostname or IPv4: 'uno-q.local', '192.168.0.48'","Drop port and path syntax — configure ports in ~/.ssh/config (Host alias plus Port) instead","IPv6 addresses are unsupported by this validator; use an SSH config alias with HostName set to the IPv6 address"],"exampleFix":"# before\nsetup_uno_q_bridge(Some(\"arduino@192.168.0.48:22\"))\n\n# after\nsetup_uno_q_bridge(Some(\"arduino@192.168.0.48\"))","handlingStrategy":"type-guard","validationCode":"let host_part = host.rsplit('@').next().unwrap_or(\"\");\nif !is_valid_ssh_host(host_part) {\n    anyhow::bail!(\"invalid host {host_part:?}: bare DNS name or IPv4 only (no ports/paths/IPv6)\");\n}\nsetup_uno_q_bridge(Some(host))?;","typeGuard":"fn is_valid_ssh_host(host: &str) -> bool {\n    !host.is_empty()\n        && host.split('.').all(|label| {\n            !label.is_empty()\n                && label.as_bytes().first().is_some_and(u8::is_ascii_alphanumeric)\n                && label.as_bytes().last().is_some_and(u8::is_ascii_alphanumeric)\n                && label.bytes().all(|b| b.is_ascii_alphanumeric() || b == b'-')\n        })\n}","tryCatchPattern":null,"preventionTips":["Pass bare hostnames/IPv4 only; put ports in ~/.ssh/config","Strip scp-style suffixes (:/path) and scheme prefixes before passing values","Use SSH Host aliases for IPv6 or exotic targets"],"tags":["input-validation","hostname","ssh-target","uno-q"],"backgroundTag":"invalid-hostname","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}