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
- Check the zbus version; upgrade or pin zbus so WellKnownName validation matches the names eww generates (validation rules changed across zbus releases).
- Sanitize the composed name: replace any character outside [A-Za-z0-9_] with '_' before try_into, and cap total length at 255.
- Print the generated name in the panic message to diagnose which character/length violated the grammar.
- 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
- Sanitize pid/counter segments to [A-Za-z0-9_] before composing the name
- Cap name length at 255 characters
- Pin/upgrade zbus deliberately; its name validation rules changed between versions
- Use ? instead of expect so retries with a new suffix are possible
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)