{"record":{"id":"8080b38606afaa40","repo":"nikivdev/code","slug":"archive-message-must-include-at-least-one-letter-o","errorCode":null,"errorMessage":"archive message must include at least one letter or number","messagePattern":"archive message must include at least one letter or number","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/archive.rs","lineNumber":26,"sourceCode":"use crate::cli::ArchiveOpts;\n\npub fn run(opts: ArchiveOpts) -> Result<()> {\n    let root =\n        ai_context::find_project_root().ok_or_else(|| anyhow::anyhow!(\"project root not found\"))?;\n    let root = fs::canonicalize(&root).unwrap_or(root);\n    let project_name = root\n        .file_name()\n        .and_then(|name| name.to_str())\n        .filter(|name| !name.trim().is_empty())\n        .unwrap_or(\"project\");\n\n    let message = opts.message.trim();\n    if message.is_empty() {\n        bail!(\"archive message cannot be empty\");\n    }\n    let slug = sanitize_segment(message);\n    if slug.is_empty() {\n        bail!(\"archive message must include at least one letter or number\");\n    }\n\n    let home = dirs::home_dir()\n        .ok_or_else(|| anyhow::anyhow!(\"could not resolve home directory\"))?\n        .to_path_buf();\n    let archive_root = home.join(\"archive\").join(\"code\");\n    fs::create_dir_all(&archive_root).with_context(|| {\n        format!(\n            \"failed to create archive directory {}\",\n            archive_root.display()\n        )\n    })?;\n\n    let code_root = fs::canonicalize(home.join(\"code\")).unwrap_or_else(|_| home.join(\"code\"));\n    let rel_path = root.strip_prefix(&code_root).ok();\n    let (dest_parent, base_project) = if let Some(rel) = rel_path {\n        let parent = rel\n            .parent()","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/nikivdev/code/blob/a747e741ae92c09071d0ae946ab48488adcff1ce/src/archive.rs#L8-L44","documentation":"Thrown by archive.rs run when the message is non-empty but sanitize_segment(message) yields an empty slug — i.e. the message contains no letters or numbers (only punctuation/symbols). The slug is used to name the archive directory, so it must be alphanumeric at least in part.","triggerScenarios":"Messages like `--message \"!!!\"` or `--message \"---\"` that survive the empty check but strip to nothing under sanitize_segment.","commonSituations":"Punctuation-only placeholder messages; templates where the meaningful text was interpolated away; shell quoting mistakes leaving only symbols.","solutions":["Include at least one letter or digit in the message, e.g. `--message \"v1-release\"`","Check interpolated template values actually render non-symbolic content","Review sanitize_segment to see which characters are retained before choosing a message"],"exampleFix":"// before\narchive --message \"!!!\"\n// after\narchive --message \"release-1\"","handlingStrategy":"validation","validationCode":"fn slug_ok(msg: &str) -> bool {\n    msg.chars().any(|c| c.is_alphanumeric())\n}\nif !slug_ok(opts.message.trim()) {\n    return Err(\"message needs at least one letter or digit\".into());\n}","typeGuard":null,"tryCatchPattern":"match archive::run(opts) {\n    Err(e) if e.to_string().contains(\"at least one letter or number\") => {\n        eprintln!(\"Message must contain alphanumeric characters.\");\n        std::process::exit(2);\n    }\n    other => other,\n}","preventionTips":["Include letters/digits in messages; avoid punctuation-only values","Check template interpolation renders meaningful text","Mirror sanitize_segment rules in caller-side validation"],"tags":["validation","slug","argument-error","cli"],"backgroundTag":"invalid-identifier","analyzedSha":"a747e741ae92c09071d0ae946ab48488adcff1ce","analyzedAt":"2026-09-01T22:43:55.719Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}