linebender/druid · error

{}

Error message

{}

What it means

Env::get<V> panics when the requested key is either absent from the environment or present with the wrong Value type; try_get returns Err whose Display message becomes the panic payload. It exists as the infallible convenience accessor for required theme keys, so the library deliberately crashes loudly instead of substituting a default. Widgets calling env.get(KEY) during paint/layout assume the key was set up in theme setup or by an ancestor.

Solutions

  1. Set the key before first use: env.set(KEY, value) in app startup (AppDelegate / main) or in the parent widget's lifecycle/init hook.
  2. Switch to env.try_get(KEY) and handle Err (missing/wrong type) with a fallback value instead of panicking.
  3. Verify the Key's type parameter matches what was stored — set with Key<Color> and read with Key<Color>, not a different variant.
  4. If the key should have a default, use the-or pattern: env.get(KEY) after env.try_get(...).unwrap_or(default), or add the key to your theme setup function all widgets share.

Example fix

// before
let color = env.get(MY_BG_COLOR); // panics if unset
// after
let color = env.try_get(MY_BG_COLOR)
    .unwrap_or(Color::WHITE);
Defensive patterns

Strategy: fallback

Validate before calling

// before calling env.get(KEY):
if env.try_get(KEY).is_err() {
    env.set(KEY, default_value);
}

Prevention

When it happens

Trigger: A custom widget calls env.get(MY_KEY) but nothing ever inserted the key via env.set / Env::with (e.g. the key isn't part of druid's default theme and the app never sets it). Calling env.get with a Key typed as one Value variant (e.g. Key<Color>) when the stored value is another (e.g. a f64 was set under the same key). Resetting or replacing the Env and dropping a key that descendants still require. Reading a key in paint_raw/resolve before the value has been provided by a parent widget.

Common situations: Custom theme keys referenced by widgets but never defined in the app's main Env setup. Renaming a Key or its type parameter in one place: Key<K> identity includes the type, and a stale setter inserts the wrong type. Copying an example that relied on druid's built-in theme (TEXT_COLOR, BUTTON_DARK, etc.) into code with a custom-built Env that omits them.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of linebender/druid@0f8b1195e4 (2026-09-10). Data as JSON: /api/errors/cb6fa1110463fd6d. Report an issue: GitHub.

Appendix: source

Thrown at druid/src/env.rs:230

    /// }
    /// ```
    ///
    /// [`WidgetExt::debug_widget`]: crate::WidgetExt::debug_widget
    pub const DEBUG_WIDGET: Key<bool> = Key::new("org.linebender.druid.built-in.debug-widget");

    /// Gets a value from the environment, expecting it to be present.
    ///
    /// Note that the return value is a reference for "expensive" types such
    /// as strings, but an ordinary value for "cheap" types such as numbers
    /// and colors.
    ///
    /// # Panics
    ///
    /// Panics if the key is not found, or if it is present with the wrong type.
    pub fn get<V: ValueType>(&self, key: impl Borrow<Key<V>>) -> V {
        match self.try_get(key) {
            Ok(value) => value,
            Err(err) => panic!("{}", err),
        }
    }

    /// Tries to get a value from the environment.
    ///
    /// If the value is not found, the raw key is returned as the error.
    ///
    /// # Panics
    ///
    /// Panics if the value for the key is found, but has the wrong type.
    pub fn try_get<V: ValueType>(&self, key: impl Borrow<Key<V>>) -> Result<V, MissingKeyError> {
        self.0
            .map
            .get(key.borrow().key)
            .map(|value| value.to_inner_unchecked())
            .ok_or(MissingKeyError {
                key: key.borrow().key.into(),
            })

View on GitHub (pinned to 0f8b1195e4)