elkowar/eww · error

generated well-known name is invalid

Error message

generated well-known name is invalid

What it means

register_as_host builds a D-Bus well-known name "org.freedesktop.StatusNotifierHost-<pid>-<i>" and converts it with WellKnownName::try_into; the expect panics if zbus rejects the name as syntactically invalid. Well-known names must match the D-Bus name grammar (elements of [A-Za-z0-9_], no element starting with a digit, total length ≤ 255).

Solutions

  1. Check the zbus version; upgrade or pin zbus so WellKnownName validation matches the names eww generates (validation rules changed across zbus releases).
  2. Sanitize the composed name: replace any character outside [A-Za-z0-9_] with '_' before try_into, and cap total length at 255.
  3. Print the generated name in the panic message to diagnose which character/length violated the grammar.
  4. Replace expect with `?` so a bad name is reported as an error and the host can retry with a different suffix.

Example fix

// before
let wellknown = format!("org.freedesktop.StatusNotifierHost-{}-{}", pid, i);
let wellknown: zbus::names::WellKnownName = wellknown.try_into().expect("generated well-known name is invalid");
// after
let raw = format!("org.freedesktop.StatusNotifierHost-{}-{}", pid, i);
let wellknown: zbus::names::WellKnownName = raw
    .try_into()
    .with_context(|| format!("generated well-known name is invalid: {}", raw))?;
Defensive patterns

Strategy: validation

Validate before calling

fn is_valid_wellknown(name: &str) -> bool {
    name.len() <= 255
        && !name.is_empty()
        && name.split('.').all(|el| !el.is_empty()
            && el.chars().all(|c| c.is_ascii_alphanumeric() || c == '_')
            && !el.chars().next().unwrap().is_ascii_digit())
}

Try / catch

match zbus::names::WellKnownName::try_from(raw.as_str()) {
    Ok(n) => /* request name */,
    Err(e) => return Err(anyhow!("invalid well-known name {}: {}", raw, e)),
}

Prevention

When it happens

Trigger: The generated name fails zbus validation — realistically only if pid or the counter formatting produces an invalid name, e.g. a pid with characters outside the allowed set (some namespaces can surface exotic pid strings) or, in older zbus versions, stricter validation rules rejecting otherwise-normal names.

Common situations: Running in containers/namespace setups with unusual pid representations, or with a zbus version whose WellKnownName validation changed, making previously accepted host names invalid.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


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

Appendix: source

Thrown at crates/notifier_host/src/host.rs:42

/// `org.freedesktop.StatusNotifierHost-{pid}-{nr}`, and registers it to active
/// StatusNotifierWatcher. The name and the StatusNotifierWatcher proxy are returned.
///
/// You still need to call [`run_host`] to have the instance of [`Host`] be notified of new and
/// removed items.
pub async fn register_as_host(
    con: &zbus::Connection,
) -> zbus::Result<(zbus::names::WellKnownName<'static>, proxy::StatusNotifierWatcherProxy<'static>)> {
    let snw = proxy::StatusNotifierWatcherProxy::new(con).await?;

    // get a well-known name
    let pid = std::process::id();
    let mut i = 0;
    let wellknown = loop {
        use zbus::fdo::RequestNameReply::*;

        i += 1;
        let wellknown = format!("org.freedesktop.StatusNotifierHost-{}-{}", pid, i);
        let wellknown: zbus::names::WellKnownName = wellknown.try_into().expect("generated well-known name is invalid");

        let flags = [zbus::fdo::RequestNameFlags::DoNotQueue];
        match con.request_name_with_flags(&wellknown, flags.into_iter().collect()).await? {
            PrimaryOwner => break wellknown,
            Exists => {}
            AlreadyOwner => {}
            InQueue => unreachable!("request_name_with_flags returned InQueue even though we specified DoNotQueue"),
        };
    };

    // register it to the StatusNotifierWatcher, so that they know there is a systray on the system
    snw.register_status_notifier_host(&wellknown).await?;

    Ok((wellknown, snw))
}

/// Run the Host forever, calling its methods as signals are received from the StatusNotifierWatcher.
///

View on GitHub (pinned to 48f5aa8b37)