{"record":{"id":"9a46d694330c0fa4","repo":"spacedriveapp/spacedrive","slug":"invalid-instance-name","errorCode":null,"errorMessage":"Invalid instance name: {}","messagePattern":"Invalid instance name: (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"apps/cli/src/main.rs","lineNumber":248,"sourceCode":"\tCloud,\n\t/// Update CLI and daemon to latest version\n\tUpdate {\n\t\t/// Force update even if already on latest version\n\t\t#[arg(long)]\n\t\tforce: bool,\n\t},\n}\n\n#[tokio::main]\nasync fn main() -> Result<()> {\n\tlet cli = Cli::parse();\n\tlet data_dir = cli.data_dir.unwrap_or(sd_core::config::default_data_dir()?);\n\tlet instance = cli.instance;\n\n\t// Validate instance name for security\n\tif let Some(ref inst) = instance {\n\t\tvalidate_instance_name(inst)\n\t\t\t.map_err(|e| anyhow::anyhow!(\"Invalid instance name: {}\", e))?;\n\t}\n\n\tlet socket_addr = if let Some(inst) = &instance {\n\t\tlet port = 6970 + (inst.bytes().map(|b| b as u16).sum::<u16>() % 1000);\n\t\tformat!(\"127.0.0.1:{}\", port)\n\t} else {\n\t\t\"127.0.0.1:6969\".to_string()\n\t};\n\n\tmatch cli.command {\n\t\tCommands::Start { foreground } => {\n\t\t\tcrate::ui::print_compact_logo();\n\t\t\tprintln!(\"Starting daemon...\");\n\n\t\t\t// Check if daemon is already running\n\t\t\tlet client = CoreClient::new(socket_addr.clone());\n\t\t\tmatch client\n\t\t\t\t.send_raw_request(&sd_core::infra::daemon::types::DaemonRequest::Ping)","sourceCodeStart":230,"sourceCodeEnd":266,"githubUrl":"https://github.com/spacedriveapp/spacedrive/blob/6dfeccf2113039e35f2ce735f945e70dc3e4ea45/apps/cli/src/main.rs#L230-L266","documentation":"The --instance flag is validated by validate_instance_name (apps/cli/src/main.rs:26) as a path-traversal guard before it is used to build socket/data paths. It rejects empty strings, names longer than 64 characters, and any character that is not alphanumeric, '-' or '_'. The wrapper anyhow! re-exports the specific reason.","triggerScenarios":"Passing --instance with '/', '.', spaces, or unicode; an empty value; a long hostname or generated ID exceeding 64 chars.","commonSituations":"Scripts interpolating user input, FQDNs, or container hostnames into --instance.","solutions":["Restrict the instance name to [A-Za-z0-9_-]{1,64}","Strip or replace forbidden characters before invoking the CLI","Remember the name also derives the port (6970 + sum of bytes % 1000), so keep it short and stable"],"exampleFix":"# before\nsd --instance 'work.laptop' status\n\n# after\nsd --instance work_laptop status","handlingStrategy":"validation","validationCode":"fn valid_instance_name(s: &str) -> bool {\n    !s.is_empty()\n        && s.len() <= 64\n        && s.chars().all(|c| c.is_alphanumeric() || c == '-' || c == '_')\n}","typeGuard":"fn sanitize_instance_name(raw: &str) -> Option<String> {\n    let cleaned: String = raw.chars().map(|c| if c.is_alphanumeric() || c == '-' || c == '_' { c } else { '_' }).collect();\n    (!cleaned.is_empty() && cleaned.len() <= 64).then_some(cleaned)\n}","tryCatchPattern":"if let Err(reason) = validate_instance_name(&instance) {\n    eprintln!(\"Instance name '{}' rejected: {}\", instance, reason);\n    std::process::exit(2); // usage error, do not retry\n}","preventionTips":["Generate instance names from a fixed [a-z0-9-_] alphabet instead of free-form hostnames","Validate at flag-parse time (clap value_parser) so failures get usage-style errors","Remember the name determines the socket port; changing it later points the CLI at a different daemon"],"tags":["cli","validation","security","arguments"],"backgroundTag":null,"analyzedSha":"6dfeccf2113039e35f2ce735f945e70dc3e4ea45","analyzedAt":"2026-08-16T11:26:17.074Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}