zellij-org/zellij · error · anyhow::Error

Unknown component: {}

Error message

Unknown component: {}

What it means

UiComponentParser::parse in zellij-server renders UI components from a byte payload decoded to a 'component_name;params...' string. It recognizes exactly four component names — table, ribbon, nested_list, text — and dispatches on the first ';'-separated token; any other first token falls through to this 'Unknown component' error. The parser is the rendering side of the custom UI-component mini-language zellij uses to draw plugin/host UI (tables, ribbons, lists, text) through the ANSI grid.

Source

Thrown at zellij-server/src/ui/components/mod.rs:124

            );
            parse_vte_bytes!(self, encoded_text);
            Ok(())
        } else if component_name == &"nested_list" {
            let nested_list_items = parse_nested_list_items(params_iter);
            let encoded_nested_list =
                nested_list(nested_list_items, &self.style, component_coordinates);
            parse_vte_bytes!(self, encoded_nested_list);
            Ok(())
        } else if component_name == &"text" {
            let stringified_params = parse_text_params(params_iter)
                .into_iter()
                .next()
                .with_context(|| format!("text must have, well, text..."))?;
            let encoded_text = text(stringified_params, &self.style, component_coordinates);
            parse_vte_bytes!(self, encoded_text);
            Ok(())
        } else {
            Err(anyhow!("Unknown component: {}", component_name))
        }
    }
    fn parse_coordinates(&self, coordinates: &str) -> Result<Option<Coordinates>> {
        lazy_static! {
            static ref RE: Regex = Regex::new(r"(\d*)/(\d*)/(\d*)/(\d*)").unwrap();
        }
        if let Some(captures) = RE.captures_iter(&coordinates).next() {
            let x = captures[1].parse::<usize>().with_context(|| {
                format!(
                    "Failed to parse x coordinates for string: {:?}",
                    coordinates
                )
            })?;
            let y = captures[2].parse::<usize>().with_context(|| {
                format!(
                    "Failed to parse y coordinates for string: {:?}",
                    coordinates
                )

View on GitHub (pinned to 98a0837077)

Solutions

  1. Use one of the four supported component names exactly: table, ribbon, nested_list, text
  2. Align versions: run the plugin against a zellij server of the same or newer release than the plugin was built for
  3. Re-check the payload format: name first, optional x/y/w/h coordinates matching d*/d*/d*/d* next, then params, all ';'-separated
  4. If a genuinely new component is needed, add a matching branch in UiComponentParser::parse rather than sending an unknown name

Example fix

// before
component_bytes = format!("TextLabel;{}", my_text).into_bytes();

// after
component_bytes = format!("text;{}", my_text).into_bytes();
Defensive patterns

Strategy: type-guard

Validate before calling

const KNOWN_COMPONENTS: [&str; 4] = ["table", "ribbon", "nested_list", "text"];

let first = payload_str.split(';').next().unwrap_or("");
if !KNOWN_COMPONENTS.contains(&first) {
    log::warn!("skipping unsupported ui component: {first}");
    return Ok(());
}

Type guard

fn is_known_component(payload: &[u8]) -> bool {
    let first = String::from_utf8_lossy(payload)
        .split(';')
        .next()
        .unwrap_or("");
    matches!(first, "table" | "ribbon" | "nested_list" | "text")
}

Try / catch

if let Err(e) = parser.parse(component_bytes) {
    if e.to_string().starts_with("Unknown component") {
        log::warn!("ignoring unknown ui component: {e:#}"); // forward-compat: skip, don't kill the render
    } else {
        return Err(e);
    }
}

Prevention

When it happens

Trigger: A component string whose first token is not table/ribbon/nested_list/text: a typo or wrong case ('Text', 'button'), a payload where the component name was never sent (params only), or a component introduced in a newer zellij being rendered by an older binary that does not know the name yet.

Common situations: Plugin/zellij version skew after upgrade (new component names on old server); hand-crafted component strings in tests or plugins with case/typo mistakes; payloads where UTF-8 lossy decoding or ';' splitting shifted the name out of position; semicolons inside the name portion.

Related errors


AI-assisted analysis of zellij-org/zellij@98a0837077 (2026-08-16). Data as JSON: /api/errors/4501a7fd76bfaee0. Report an issue: GitHub.