emilk/egui · error
Invalid hex color length: expected 3 (RGB) or 4 (RGBA) bytes
Error message
Invalid hex color length: expected 3 (RGB) or 4 (RGBA) bytes
What it means
This panic comes from the `hex_color!` macro in ecolor, which parses a hex string literal into a `Color32` at compile/const time. After decoding the hex digits, the resulting byte slice must contain exactly 3 (RGB) or 4 (RGBA) values; any other count means the hex string had an unexpected number of digits (e.g. 6-digit `#RRGGBB` or 8-digit `#RRGGBBAA` instead of the `0xRRGGBB`-byte style the macro expects). The macro cannot recover, so it panics.
Source
Thrown at crates/ecolor/src/hex_color_macro.rs:47
///
/// ```compile_fail
/// let _ = ecolor::hex_color!("#20212x");
/// ```
///
/// The macro can be used in a `const` context.
///
/// ```
/// const COLOR: ecolor::Color32 = ecolor::hex_color!("#202122");
/// assert_eq!(COLOR, ecolor::Color32::from_rgb(0x20, 0x21, 0x22));
/// ```
#[macro_export]
macro_rules! hex_color {
($s:literal) => {{
let array = $crate::color_hex::color_from_hex!($s);
match array.as_slice() {
[r, g, b] => $crate::Color32::from_rgb(*r, *g, *b),
[r, g, b, a] => $crate::Color32::from_rgba_unmultiplied_const(*r, *g, *b, *a),
_ => panic!("Invalid hex color length: expected 3 (RGB) or 4 (RGBA) bytes"),
}
}};
}
#[test]
fn test_from_rgb_hex() {
assert_eq!(
crate::Color32::from_rgb(0x20, 0x21, 0x22),
hex_color!("#202122")
);
assert_eq!(
crate::Color32::from_rgb_additive(0x20, 0x21, 0x22),
hex_color!("#202122").additive()
);
}
#[test]
fn test_from_rgba_hex() {View on GitHub (pinned to 441971a776)
Solutions
- Check the hex literal: it must produce exactly 3 or 4 bytes (e.g. `hex_color!("0xFF00FF")` or RGBA with alpha); add an alpha pair or fix truncation.
- If you have a CSS-style #RRGGBB string, convert it to the byte-format the macro expects (two hex digits per byte, e.g. #3465A4 -> 0x34,0x65,0xA4 style accepted by color_from_hex!).
- For runtime strings, don't use the macro; use `Color32::from_hex` which returns a Result instead of panicking.
- Read the panic output and confirm the literal's decoded byte count is 3 or 4; add or remove hex digit pairs accordingly.
Example fix
// before
let c = hex_color!("#3465a4"); // 6 hex digits -> wrong byte count -> panic
// after
let c = hex_color!("0x3465a4ff"); // bytes: [0x34, 0x65, 0xa4, 0xff] -> RGBA Color32 Defensive patterns
Strategy: validation
Validate before calling
let s = "#3465a4";
let digits = s.trim_start_matches('#');
assert!(digits.len() == 6 || digits.len() == 8, "hex_color! expects byte pairs yielding 3 or 4 bytes"); Type guard
fn is_valid_hex_color(s: &str) -> bool {
let d = s.trim_start_matches("0x").trim_start_matches('#');
(d.len() == 6 || d.len() == 8) && d.chars().all(|c| c.is_ascii_hexdigit())
} Prevention
- Use Color32::from_hex (Result-based) for dynamic/runtime strings instead of the panic-prone macro.
- Only pass string literals in the byte-pair format the macro supports; never paste CSS #RRGGBB directly without checking.
- Write a unit test per color literal so a bad format fails the build/test run explicitly.
When it happens
Trigger: Calling `hex_color!("...")` with a literal that decodes to a byte-array length other than 3 or 4 — typically a 6-digit (#RRGGBB) or 8-digit (#RRGGBBAA) CSS-style hex string instead of the expected format that yields 3 or 4 bytes, or a truncated/odd string like "ff00" producing 2 bytes.
Common situations: Developers copying a CSS color like `#3465a4` (6 hex digits) into `hex_color!` expecting CSS syntax; editing a color literal and accidentally deleting characters; writing an 8-digit CSS hex with alpha and having it decode to the wrong byte count for this macro's contract.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
AI-assisted analysis of emilk/egui@441971a776 (2026-09-12).
Data as JSON: /api/errors/b8e0d5715195852e.
Report an issue: GitHub.