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

  1. 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.
  2. 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!).
  3. For runtime strings, don't use the macro; use `Color32::from_hex` which returns a Result instead of panicking.
  4. 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

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.