Kuberwastaken/claurst · error
Plugin name ' ' cannot contain spaces. Use kebab-case.
Error message
Plugin name '{}' cannot contain spaces. Use kebab-case. What it means
Plugin manifest names must be kebab-case; the validator rejects any name containing a space character. This keeps plugin names valid as identifiers on disk, in registries, and in CLI references, matching the TS schema checks.
Solutions
- Replace spaces in the name with hyphens, e.g. "My Plugin" -> "my-plugin"
- Lowercase the name to conform to kebab-case conventions
- Keep the human-readable title in a separate display-name field if the schema supports one
Example fix
// before (plugin.toml) name = "My Plugin" // after name = "my-plugin"
Defensive patterns
Strategy: validation
Validate before calling
fn kebab_case(name: &str) -> bool {
!name.is_empty() && !name.contains(' ') && name.chars().all(|c| c.is_ascii_lowercase() || c == '-' || c.is_ascii_digit())
} Try / catch
match PluginManifest::from_toml(&toml_str) {
Err(e) if e.to_string().contains("cannot contain spaces") => { /* normalize name to kebab-case */ }
other => other?,
} Prevention
- Always derive plugin names from kebab-case identifiers, not display names
- Keep human-readable titles in a separate description/display field
- Lint manifest names in CI for spaces and uppercase characters
When it happens
Trigger: PluginManifest::validate (via from_toml) sees a name value containing at least one ' ' character, e.g. name = "My Plugin".
Common situations: Author wrote a display name instead of an identifier in plugin.toml; renaming a plugin to a human-friendly label; copied name from a README heading.
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
- Plugin name cannot be empty
- Invalid env-var format
- source settings.json must be a JSON object
- mcpServers must be an object
- mcpServers. must be an object
AI-assisted analysis of Kuberwastaken/claurst@b0637c97ec (2026-09-10).
Data as JSON: /api/errors/6b580788fb81719e.
Report an issue: GitHub.
Appendix: source
Thrown at src-rust/crates/plugins/src/manifest.rs:347
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,
};
// Promote `mcpServers` (TS camelCase object) → `mcp_servers` (array).View on GitHub (pinned to b0637c97ec)