Kuberwastaken/claurst · error

Plugin name cannot be empty

Error message

Plugin name cannot be empty

What it means

Sentinel validation error from PluginManifest::validate: the parsed plugin manifest (from plugin.json or plugin.toml) has an empty `name` field, i.e. the file is missing a name or declares name = "". Fired after successful deserialization, so the file itself was syntactically valid.

Solutions

  1. Set a non-empty name in the plugin manifest file
  2. Use kebab-case for the name (lowercase words separated by hyphens) to also pass the spaces check
  3. Re-run plugin loading after editing the manifest

Example fix

// before (plugin.toml)
name = ""
// after
name = "my-plugin"
Defensive patterns

Strategy: validation

Validate before calling

fn manifest_name_ok(m: &PluginManifest) -> bool { !m.name.is_empty() }

Try / catch

match PluginManifest::from_toml(&toml_str) {
    Err(e) if e.to_string().contains("name cannot be empty") => { /* prompt for a name */ }
    other => other?,
}

Prevention

When it happens

Trigger: Calling PluginManifest::validate (typically via from_toml) on a manifest whose name field is the empty string.

Common situations: Manually created plugin.toml with the name key omitted (if it defaults to empty) or left blank; a code generator emitted an empty name; template file not filled in.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of Kuberwastaken/claurst@b0637c97ec (2026-09-10). Data as JSON: /api/errors/77b888bdd2560977. Report an issue: GitHub.

Appendix: source

Thrown at src-rust/crates/plugins/src/manifest.rs:344

        let v: serde_json::Value = serde_json::from_slice(bytes)?;
        // Handle both `mcpServers` (object) and `mcp_servers` (array) keys.
        let manifest = serde_json::from_value::<PluginManifest>(normalize_manifest_json(v))?;
        manifest.validate()?;
        Ok(manifest)
    }

    /// Parse a manifest from TOML bytes (plugin.toml).
    pub fn from_toml(bytes: &[u8]) -> anyhow::Result<Self> {
        let s = std::str::from_utf8(bytes)?;
        let manifest: PluginManifest = toml::from_str(s)?;
        manifest.validate()?;
        Ok(manifest)
    }

    /// Basic validation matching the TS schema checks.
    pub fn validate(&self) -> anyhow::Result<()> {
        if self.name.is_empty() {
            anyhow::bail!("Plugin name cannot be empty");
        }
        if self.name.contains(' ') {
            anyhow::bail!(
                "Plugin name '{}' cannot contain spaces. Use kebab-case.",
                self.name
            );
        }
        Ok(())
    }
}

/// Normalise the raw JSON value so that both camelCase and snake_case
/// variants of known fields work, and so `mcpServers` (object mapping) is
/// converted to a `Vec<PluginMcpServer>`.
fn normalize_manifest_json(mut v: serde_json::Value) -> serde_json::Value {
    let obj = match v.as_object_mut() {
        Some(o) => o,
        None => return v,

View on GitHub (pinned to b0637c97ec)