{"record":{"id":"481a928fe30baa99","repo":"microsoft/edit","slug":"unrecognized-gcb-for-u-04x-to-u-04x","errorCode":null,"errorMessage":"Unrecognized GCB={} for U+{:04X} to U+{:04X}","messagePattern":"Unrecognized GCB=(.+?) for U\\+(.+?) to U\\+(.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/unicode-gen/src/main.rs","lineNumber":807,"sourceCode":"\n            let mut cb = match char_attributes.grapheme_cluster_break {\n                \"XX\" => ClusterBreak::Other, // Anything else\n                // We ignore GB3 which demands that CR × LF do not break apart, because\n                // * these control characters won't normally reach our text storage\n                // * otherwise we're in a raw write mode and historically conhost stores them in separate cells\n                \"CR\" => ClusterBreak::CR,            // Carriage Return\n                \"LF\" => ClusterBreak::LF,            // Line Feed\n                \"CN\" => ClusterBreak::Control,       // Control\n                \"EX\" | \"SM\" => ClusterBreak::Extend, // Extend, SpacingMark\n                \"PP\" => ClusterBreak::Prepend,       // Prepend\n                \"ZWJ\" => ClusterBreak::ZWJ,          // Zero Width Joiner\n                \"RI\" => ClusterBreak::RI,            // Regional Indicator\n                \"L\" => ClusterBreak::HangulL,        // Hangul Syllable Type L\n                \"V\" => ClusterBreak::HangulV,        // Hangul Syllable Type V\n                \"T\" => ClusterBreak::HangulT,        // Hangul Syllable Type T\n                \"LV\" => ClusterBreak::HangulLV,      // Hangul Syllable Type LV\n                \"LVT\" => ClusterBreak::HangulLVT,    // Hangul Syllable Type LVT\n                _ => bail!(\n                    \"Unrecognized GCB={} for U+{:04X} to U+{:04X}\",\n                    char_attributes.grapheme_cluster_break,\n                    range.start(),\n                    range.end()\n                ),\n            };\n\n            if char_attributes.extended_pictographic == \"Y\" {\n                // Currently every single Extended_Pictographic codepoint happens to be GCB=XX.\n                // This is fantastic for us because it means we can stuff it into the ClusterBreak enum\n                // and treat it as an alias of EXTEND, but with the special GB11 properties.\n                if cb != ClusterBreak::Other {\n                    bail!(\n                        \"Unexpected GCB={} with ExtPict=Y for U+{:04X} to U+{:04X}\",\n                        char_attributes.grapheme_cluster_break,\n                        range.start(),\n                        range.end()\n                    );","sourceCodeStart":789,"sourceCodeEnd":825,"githubUrl":"https://github.com/microsoft/edit/blob/826b4c097b6f14ba0a846dc56f2f0223a3aaf73a/crates/unicode-gen/src/main.rs#L789-L825","documentation":"While extracting Grapheme_Cluster_Break values from the UCD XML, any GCB string not in the known mapping (XX/Other, CR, LF, Control, Extend, ZWJ, RI, L, V, T, LV, LVT, Prepend, SpacingMark, Extend*) hits the catch-all bail. This keeps generated tables exhaustive over the enum — unknown Unicode data is refused rather than silently mis-encoded.","triggerScenarios":"Feeding unicode-gen a UCD XML file from a Unicode version that introduces a GCB property value the generator does not know, or a corrupted/modified GraphemeBreakProperty file with a bad gcb attribute.","commonSituations":"Upgrading to a newer Unicode release before updating the ClusterBreak enum; hand-edited or truncated UCD data; using the wrong UCD file (e.g. one with different attributes).","solutions":["Use the UCD XML version matching the generator's supported Unicode release.","Add the new GCB value to the ClusterBreak enum and its mapping arm in extract_values_from_ucd, then regenerate.","Verify the input file's integrity (re-download the official UCD archive) if the value looks corrupt."],"exampleFix":"// before\n_ => bail!(\"Unrecognized GCB={} ...\"),\n// after\n\"NewValue\" => ClusterBreak::NewValue,\n_ => bail!(\"Unrecognized GCB={} ...\"),","handlingStrategy":"try-catch","validationCode":"// pre-check GCB values in the UCD XML before generating\nfor node in doc.descendants().filter(|n| n.has_attribute(\"gcb\")) {\n    const KNOWN: &[&str] = &[\"XX\",\"CR\",\"LF\",\"Control\",\"Extend\",\"ZWJ\",\"RI\",\"L\",\"V\",\"T\",\"LV\",\"LVT\",\"Prepend\",\"SpacingMark\"];\n    let v = node.attribute(\"gcb\").unwrap();\n    assert!(KNOWN.contains(&v), \"unsupported GCB value {v} in UCD file\");\n}","typeGuard":null,"tryCatchPattern":"// wrap generation and report the offending range\nif let Err(e) = generate(&ucd_path) {\n    let msg = e.to_string();\n    if msg.starts_with(\"Unrecognized GCB=\") {\n        eprintln!(\"UCD version too new for this generator: {msg}\");\n        std::process::exit(1);\n    }\n    return Err(e);\n}","preventionTips":["Pin the UCD download URL to the Unicode version the generator supports.","Checksum UCD files to detect corruption before generation.","When upgrading Unicode, diff the new property values against the ClusterBreak enum first."],"tags":["unicode","codepoint-data","unrecognized-value"],"backgroundTag":"invalid-enum-value","analyzedSha":"826b4c097b6f14ba0a846dc56f2f0223a3aaf73a","analyzedAt":"2026-09-06T13:30:05.543Z","contentChangedAt":"2026-09-06T13:30:05.543Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}