elkowar/eww · error

This widget can only be used as a child of some container…

Error message

This widget can only be used as a child of some container widget such as box

What it means

build_gtk_widget constructs the GTK widget tree from the yuck AST. WidgetUse::Loop and WidgetUse::Children nodes are special constructs that only make sense as direct children of container widgets (which expand them); encountered anywhere else, eww raises this diagnostic suggesting wrapping in a box.

Solutions

  1. Wrap the loop/children node in a `box` (or another container widget)
  2. Move the construct into a container widget's child list
  3. Restructure the custom widget so children are consumed by a container

Example fix

; before
(box (for i in {"1 2 3"} (label :text i)) (children))
; children directly under non-container context

; after
(box
  (box (for i in {"1 2 3"} (label :text i)))
  (box (children)))
Defensive patterns

Strategy: validation

Validate before calling

// pre-check node type before building
let buildable = !matches!(widget_use, WidgetUse::Loop(_) | WidgetUse::Children(_));
if !buildable { /* wrap in box first */ }

Try / catch

match build_gtk_widget(...) {
    Ok(w) => w,
    Err(e) => { eprintln!("widget build failed: {e:#}"); gtk::Label::new(Some("widget error")).upcast() }
}

Prevention

When it happens

Trigger: Using `(for ...)`/`(loop ...)` or `(children)` (or a custom widget invocation that expands to children) directly where a plain widget is expected — i.e. not inside box/other container whose child-population handles these node types.

Common situations: Putting a loop at the top level of a window definition without a container; nesting `children` inside a widget that isn't a container; misuse of custom widget definitions that yield children nodes.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of elkowar/eww@48f5aa8b37 (2026-09-08). Data as JSON: /api/errors/9a56d2beaa2c4ffe. Report an issue: GitHub.

Appendix: source

Thrown at crates/eww/src/widgets/build_widget.rs:60

// TODO in case of custom widgets, we should add a validation step where
// warnings for unknown attributes (attributes not expected by the widget) are emitted.

/// Build a [`gtk::Widget`] out of a [`WidgetUse`].
/// This will set up scopes in the [`ScopeGraph`], register all the listeners there,
/// and recursively generate all the widgets and child widgets.
pub fn build_gtk_widget(
    graph: &mut ScopeGraph,
    widget_defs: Rc<HashMap<String, WidgetDefinition>>,
    calling_scope: ScopeIndex,
    widget_use: WidgetUse,
    custom_widget_invocation: Option<Rc<CustomWidgetInvocation>>,
) -> Result<gtk::Widget> {
    match widget_use {
        WidgetUse::Basic(widget_use) => {
            build_basic_gtk_widget(graph, widget_defs, calling_scope, widget_use, custom_widget_invocation)
        }
        WidgetUse::Loop(_) | WidgetUse::Children(_) => Err(anyhow::anyhow!(DiagError(gen_diagnostic! {
            msg = "This widget can only be used as a child of some container widget such as box",
            label = widget_use.span(),
            note = "Hint: try wrapping this in a `box`"
        }))),
    }
}

fn build_basic_gtk_widget(
    graph: &mut ScopeGraph,
    widget_defs: Rc<HashMap<String, WidgetDefinition>>,
    calling_scope: ScopeIndex,
    mut widget_use: BasicWidgetUse,
    custom_widget_invocation: Option<Rc<CustomWidgetInvocation>>,
) -> Result<gtk::Widget> {
    if let Some(custom_widget) = widget_defs.clone().get(&widget_use.name) {
        let widget_use_attributes = custom_widget
            .expected_args
            .iter()

View on GitHub (pinned to 48f5aa8b37)