{"record":{"id":"36d98792458ff326","repo":"SubtitleEdit/subtitleedit","slug":"invalid-hex-string","errorCode":null,"errorMessage":"Invalid hex string.","messagePattern":"Invalid hex string\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/ui/Logic/AvaloniaColorExtensions.cs","lineNumber":27,"sourceCode":"    /// <summary>\n    /// Converts an Color to a hex string. Default is ARGB (#AARRGGBB).\n    /// Set includeAlpha to false for RGB (#RRGGBB).\n    /// </summary>\n    public static string FromColorToHex(this Avalonia.Media.Color color, bool includeAlpha = true)\n    {\n        return includeAlpha\n            ? $\"#{color.A:X2}{color.R:X2}{color.G:X2}{color.B:X2}\" // ARGB\n            : $\"#{color.R:X2}{color.G:X2}{color.B:X2}\";            // RGB\n    }\n\n    /// <summary>\n    /// Converts a hex string (e.g., \"#RRGGBB\" or \"#AARRGGBB\") to a Color.\n    /// </summary>\n    public static Avalonia.Media.Color FromHexToColor(this string hex)\n    {\n        if (string.IsNullOrWhiteSpace(hex))\n        {\n            throw new ArgumentException(\"Invalid hex string.\");\n        }\n\n        hex = hex.TrimStart('#');\n\n        byte a = 255, r, g, b;\n\n        if (hex.Length == 6)\n        {\n            // Format: RRGGBB\n            r = byte.Parse(hex.Substring(0, 2), NumberStyles.HexNumber);\n            g = byte.Parse(hex.Substring(2, 2), NumberStyles.HexNumber);\n            b = byte.Parse(hex.Substring(4, 2), NumberStyles.HexNumber);\n        }\n        else if (hex.Length == 8)\n        {\n            // Format: AARRGGBB\n            a = byte.Parse(hex.Substring(0, 2), NumberStyles.HexNumber);\n            r = byte.Parse(hex.Substring(2, 2), NumberStyles.HexNumber);","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/SubtitleEdit/subtitleedit/blob/17a9f0748781032255db3526b7215d2fb891e3af/src/ui/Logic/AvaloniaColorExtensions.cs#L9-L45","documentation":"Thrown by AvaloniaColorExtensions.FromHexToColor when the input string is null, empty, or whitespace. This is the first guard before TrimStart('#') and length parsing, so a missing/blank color value aborts with an ArgumentException rather than producing a misleading parse error downstream.","triggerScenarios":"Passing null/\"\"/\"   \" to FromHexToColor: an unset color setting serialized as null, a missing theme/style attribute, or a defaulted config value that was never populated.","commonSituations":"A color settings field defaulted to null after a settings reset; deserializing an old config missing a newly-added color key; UI binding a null color value into a hex converter.","solutions":["Coalesce null/blank to a default color before calling FromHexToColor.","Ensure settings/theme files always serialize a hex value for color keys.","Validate user-entered hex input is non-empty before parsing."],"exampleFix":"// before\nvar color = userHex.FromHexToColor();\n\n// after - default to a safe color when blank\nvar color = (string.IsNullOrWhiteSpace(userHex) ? \"#FFFFFFFF\" : userHex).FromHexToColor();","handlingStrategy":"validation","validationCode":"if (string.IsNullOrWhiteSpace(hex)) hex = \"#FFFFFFFF\"; // or throw with context\n// or guard at the call site:\nif (string.IsNullOrWhiteSpace(userHex)) { /* use default color */ return defaultColor; }","typeGuard":"static bool IsHexColor(this string? s) => !string.IsNullOrWhiteSpace(s);","tryCatchPattern":null,"preventionTips":["Always serialize a default hex value for color settings.","Coalesce null/blank to a default before parsing.","Validate user input at the UI layer, not in the converter."],"tags":["color","hex","validation","avalonia"],"backgroundTag":null,"analyzedSha":"17a9f0748781032255db3526b7215d2fb891e3af","analyzedAt":"2026-08-13T18:11:43.374Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}