{"record":{"id":"83e6c6395e1ae1f0","repo":"zed-industries/zed","slug":"invalid-rgba-hex-color-value-expected-rgb","errorCode":null,"errorMessage":"invalid RGBA hex color: '{value}'. Expected #rgb, #rgba, #rrggbb, or #rrggbbaa","messagePattern":"invalid RGBA hex color: '(.+?)'\\. Expected #rgb, #rgba, #rrggbb, or #rrggbbaa","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/gpui/src/color.rs","lineNumber":237,"sourceCode":"            a: color.a,\n        }\n    }\n}\n\nimpl TryFrom<&'_ str> for Rgba {\n    type Error = anyhow::Error;\n\n    fn try_from(value: &'_ str) -> Result<Self, Self::Error> {\n        const RGB: usize = \"rgb\".len();\n        const RGBA: usize = \"rgba\".len();\n        const RRGGBB: usize = \"rrggbb\".len();\n        const RRGGBBAA: usize = \"rrggbbaa\".len();\n\n        const EXPECTED_FORMATS: &str = \"Expected #rgb, #rgba, #rrggbb, or #rrggbbaa\";\n        const INVALID_UNICODE: &str = \"invalid unicode characters in color\";\n\n        let Some((\"\", hex)) = value.trim().split_once('#') else {\n            bail!(\"invalid RGBA hex color: '{value}'. {EXPECTED_FORMATS}\");\n        };\n\n        let (r, g, b, a) = match hex.len() {\n            RGB | RGBA => {\n                let r = u8::from_str_radix(\n                    hex.get(0..1).with_context(|| {\n                        format!(\"{INVALID_UNICODE}: r component of #rgb/#rgba for value: '{value}'\")\n                    })?,\n                    16,\n                )?;\n                let g = u8::from_str_radix(\n                    hex.get(1..2).with_context(|| {\n                        format!(\"{INVALID_UNICODE}: g component of #rgb/#rgba for value: '{value}'\")\n                    })?,\n                    16,\n                )?;\n                let b = u8::from_str_radix(\n                    hex.get(2..3).with_context(|| {","sourceCodeStart":219,"sourceCodeEnd":255,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/gpui/src/color.rs#L219-L255","documentation":"TryFrom<&str> for Rgba trims the input and splits once on '#'; the parse only succeeds when the result is exactly (\"\", hex), i.e. a pure '#'-prefixed literal. This first bail fires when there is no '#' at all, or when text precedes the '#'. CSS color functions and named colors are not supported by this parser.","triggerScenarios":"Converting strings like ff0000 (missing '#'), rgb(255,0,0), red, or 'color: #ff0000' into Rgba via theme or settings parsing, or any API that accepts color strings.","commonSituations":"Hand-edited theme or settings files using CSS syntax instead of hex; copy-pasted colors without the '#'; strings with labels or prefixes from other config formats.","solutions":["Use one of the accepted literals: #rgb, #rgba, #rrggbb, #rrggbbaa","If input is user-facing, strip non-hex prefixes and add the '#' before conversion","Validate color strings at settings load time so the error names the offending key"],"exampleFix":"// before\nlet color = Rgba::try_from(\"1e1e2e\")?; // no '#' -> bail\n\n// after\nlet color = Rgba::try_from(\"#1e1e2e\")?;","handlingStrategy":"validation","validationCode":"fn is_valid_hex_color(value: &str) -> bool {\n    let Some(hex) = value.trim().strip_prefix('#') else { return false };\n    matches!(hex.len(), 3 | 4 | 6 | 8) && hex.chars().all(|c| c.is_ascii_hexdigit())\n}","typeGuard":"fn is_hex_color(value: &str) -> bool {\n    value.trim().starts_with('#') && value.trim().chars().skip(1).all(|c| c.is_ascii_hexdigit())\n}","tryCatchPattern":"let color = Rgba::try_from(raw).with_context(|| format!(\"invalid color '{raw}' for setting '{key}'\"))?;","preventionTips":["Store colors as typed Rgba values, not strings, wherever possible","Validate all color fields when loading settings or themes and report the offending key","Document the four accepted formats next to user-facing color settings"],"tags":["gpui","color","parsing","settings","theme"],"backgroundTag":"invalid-color-format","analyzedSha":"f4178619acd0d47ea1f76a2025c42962c6d6638c","analyzedAt":"2026-08-20T19:29:52.058Z","contentChangedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}