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

  1. Add a "name" field - when only name is given, id defaults to the same value
  2. Or add an explicit unique "id" (id alone is also accepted)
  3. 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

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


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/40318b9e1a6e663d. Report an issue: GitHub.