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
- Use one of the four supported component names exactly: table, ribbon, nested_list, text
- Align versions: run the plugin against a zellij server of the same or newer release than the plugin was built for
- Re-check the payload format: name first, optional x/y/w/h coordinates matching d*/d*/d*/d* next, then params, all ';'-separated
- 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
- Keep component-name vocabulary in one shared constant used by both sender and parser
- Version-gate new component names so old servers never receive them
- Add a fast allowlist check before invoking UiComponentParser::parse
- Never rely on case-insensitivity: matching is exact
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.