gitbutlerapp/gitbutler · error · anyhow::Error
id or name must be specified
Error message
id or name must be specified
What it means
User-defined programs are deserialized from the user-defined programs JSON file in the app config dir (USER_DEFINED_PROGRAMS_FILENAME) into UserDefinedProgramSpec values, then converted via try_into_program_spec(). When a spec matches no builtin program id and has neither id nor name, there is no identifier to register the program under, so conversion bails. Through list_programs()/list_editors() this is actually a soft failure: the entry is dropped with a 'Failed to decode user defined program specification' warning, so the program just silently disappears from the list.
Source
Thrown at crates/but-api/src/open/program.rs:741
id: id.clone(),
name: self.name.unwrap_or_else(|| builtin.name.clone()),
executable: self
.executable
.map(Into::into)
.unwrap_or_else(|| builtin.executable.clone()),
category: self
.category
.map(Into::into)
.unwrap_or_else(|| builtin.category.clone()),
cli_arg_supplier,
extensions,
})
} else {
let (name, id) = match (self.name, self.id) {
(Some(name), Some(id)) => (name, id),
(Some(name), None) => (name.clone(), name),
(None, Some(id)) => (id.clone(), id),
(None, None) => anyhow::bail!("id or name must be specified"),
};
let Some(executable) = self.executable else {
anyhow::bail!("executable must be specified for non built-ins")
};
Ok(ProgramSpec {
id,
name,
executable: executable.into(),
category: self.category.map(Into::into).unwrap_or_default(),
cli_arg_supplier: CliArgumentSupplier::Custom(CustomCliArgumentSupplier {
open_args: self.open_args,
open_at_line_args: self.open_at_line_args,
}),
extensions,
})
}View on GitHub (pinned to caf1f223d3)
Solutions
- Add a "name" field - when only name is given, id defaults to the same value
- Or add an explicit unique "id" (id alone is also accepted)
- Re-run list_programs()/list_editors() and confirm the entry now appears; check logs for the warn if it still does not
Example fix
// before (user-defined-programs.json entry)
{ "executable": { "type": "pathExecutable", "path": "/usr/local/bin/helix" } }
// after
{ "name": "Helix", "executable": { "type": "pathExecutable", "path": "/usr/local/bin/helix" } } Defensive patterns
Strategy: validation
Validate before calling
// Validate a user-defined programs entry before writing/using it
function hasIdentifier(entry: { id?: unknown; name?: unknown }): boolean {
return typeof entry.id === 'string' && entry.id.length > 0
|| typeof entry.name === 'string' && entry.name.length > 0;
}
const valid = entries.filter(hasIdentifier); Type guard
interface ProgramEntry { id?: string; name?: string; executable?: unknown; openArgs?: string[]; openAtLineArgs?: string[]; category?: string; extensions?: string[] }
function isUsableProgramEntry(e: ProgramEntry): boolean {
return typeof e.id === 'string' || typeof e.name === 'string';
} Prevention
- Always set at least 'name' when writing user-defined program entries - id then defaults to it
- After editing the user-defined programs file, run list_programs/list_editors and check logs for 'Failed to decode user defined program specification' warns (entries fail silently there)
- Validate entries with a schema before persisting, not after the app filters them out
When it happens
Trigger: A user-defined-programs JSON entry like {"executable": {"type": "pathExecutable", ...}} with both "id" and "name" absent or null. Direct callers of UserDefinedProgramSpec::try_into_program_spec get the Err; the settings/listing path filters it out with a tracing::warn.
Common situations: Hand-editing the user-defined programs file and omitting "name"; a settings-sync or migration tool writing partial objects; older file formats that assumed a different required-field set.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- executable must be specified for non built-ins
- Unknown terminal: {terminal_id}
- Invalid message format
- HTTP Error ${response.statusText}: ${text}
- Please sign in to use GitButler's AI API
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/40318b9e1a6e663d.
Report an issue: GitHub.