{"record":{"id":"a4851b95b68090d8","repo":"Hmbown/CodeWhale","slug":"invalid-runtime-chat-label","errorCode":null,"errorMessage":"invalid Runtime Chat {label}","messagePattern":"invalid Runtime Chat (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/runtime_chat_relay.rs","lineNumber":1697,"sourceCode":"    #[cfg(test)]\n    if take_state_persist_failure(path) {\n        bail!(\"injected Runtime Chat state persistence failure\");\n    }\n    let body = serde_json::to_vec(state).context(\"encode Runtime Chat binding state\")?;\n    crate::utils::write_atomic(path, &body).context(\"persist Runtime Chat binding state\")\n}\n\nfn validate_relay_id(value: &str, label: &str) -> Result<()> {\n    if value.is_empty()\n        || value.len() > MAX_RELAY_ID_BYTES\n        || value.contains(\"..\")\n        || value.contains(\"://\")\n        || !value.bytes().all(|byte| {\n            byte.is_ascii_alphanumeric()\n                || matches!(byte, b'.' | b'_' | b':' | b'@' | b'/' | b'+' | b'~' | b'-')\n        })\n    {\n        bail!(\"invalid Runtime Chat {label}\");\n    }\n    Ok(())\n}\n\nfn validate_operation_key(value: &str) -> Result<()> {\n    validate_relay_id(value, \"operation key\")?;\n    if value.len() > MAX_OPERATION_KEY_BYTES {\n        bail!(\"Runtime Chat operation key is too long\");\n    }\n    Ok(())\n}\n\nfn validate_virtual_thread_id(value: &str) -> Result<()> {\n    if value.len() != 37\n        || !value.starts_with(\"local_thread_\")\n        || !value[13..]\n            .bytes()\n            .all(|byte| byte.is_ascii_digit() || matches!(byte, b'a'..=b'f'))","sourceCodeStart":1679,"sourceCodeEnd":1715,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/runtime_chat_relay.rs#L1679-L1715","documentation":"validate_relay_id is the shared identifier validator for Runtime Chat relay ids (run id, route labels, operation keys, etc.). It rejects values that are empty, too long, contain \"://\", or contain any byte outside the allowed ASCII set (alphanumeric plus . _ : @ / + ~ -). The bail includes the caller-provided label, e.g. \"invalid Runtime Chat run id\".","triggerScenarios":"Any validate_relay_id(value, label) call (directly or via validate_operation_key, validate_relay_id wrappers in validate()) receiving a value that is empty, contains \"://\", or has disallowed characters (spaces, Unicode, control bytes, %, ?, &, etc.).","commonSituations":"Passing a full URL where a bare id is expected (the \"://\" check specifically catches this); user-supplied thread or route names with spaces or non-ASCII characters; ids with percent-encoding or query strings; empty strings from failed lookups.","solutions":["Strip the scheme from URLs and pass only the bare id portion (remove \"://...\")","Replace disallowed characters with allowed ones (. _ : @ / + ~ - or alphanumeric)","Check that the value is non-empty before validating","Restrict upstream input to ASCII identifiers (e.g. a regex like ^[A-Za-z0-9._:@/+~-]+$)"],"exampleFix":"// before\nlet id = \"https://example.com/run/abc\"; // contains \"://\"\n// after\nlet id = \"example.com/run/abc\";","handlingStrategy":"validation","validationCode":"const RELAY_ID_RE: once_cell::sync::Lazy<regex::Regex> = once_cell::sync::Lazy::new(\n    || regex::Regex::new(r\"^[A-Za-z0-9._:@/+~-]+$\").unwrap(),\n);\nfn is_valid_relay_id(value: &str) -> bool {\n    !value.is_empty() && !value.contains(\"://\") && RELAY_ID_RE.is_match(value)\n}","typeGuard":"fn as_relay_id(value: &str) -> Option<&str> {\n    (!value.is_empty()\n        && !value.contains(\"://\")\n        && value.bytes().all(|b| b.is_ascii_alphanumeric()\n            || matches!(b, b'.' | b'_' | b':' | b'@' | b'/' | b'+' | b'~' | b'-')))\n    .then_some(value)\n}","tryCatchPattern":"match validate_relay_id(&id, \"run id\") {\n    Ok(()) => { /* proceed */ }\n    Err(e) => {\n        eprintln!(\"{e}: sanitizing id before use\");\n        let id = sanitize_relay_id(&id); // strip scheme, replace bad chars\n    }\n}","preventionTips":["Never pass full URLs where the API expects a bare relay id (\"://\" is explicitly rejected)","Constrain user-supplied ids at input time to [A-Za-z0-9._:@/+~-]","Sanitize provider-supplied identifiers before storing them in relay state"],"tags":["validation","identifier","format"],"backgroundTag":"invalid-argument-format","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}