zed-industries/zed · warning · anyhow::Error

Cannot remove a keybinding that does not exist

Error message

Cannot remove a keybinding that does not exist

What it means

remove_keybinding walks the user keymap file to delete the entry matching a ProcessedBinding; the removal machinery matches on keystrokes, so a binding with no keystrokes (existing.keystrokes() == None) cannot be located and the function refuses rather than corrupting the file.

Source

Thrown at crates/keymap_editor/src/keymap_editor.rs:3697

    .context("Failed to write keymap file")?;

    telemetry::event!(
        "Keybinding Updated",
        new_keybinding = new_keybinding,
        removed_keybinding = removed_keybinding,
        source = source
    );
    Ok(())
}

async fn remove_keybinding(
    existing: ProcessedBinding,
    fs: &Arc<dyn Fs>,
    keyboard_mapper: &dyn PlatformKeyboardMapper,
    deprecated_aliases: &HashMap<&'static str, &'static str>,
) -> anyhow::Result<()> {
    let Some(keystrokes) = existing.keystrokes() else {
        anyhow::bail!("Cannot remove a keybinding that does not exist");
    };
    let keymap_contents = settings::KeymapFile::load_keymap_file(fs)
        .await
        .context("Failed to load keymap file")?;
    let tab_size = infer_json_indent_size(&keymap_contents);

    let operation = settings::KeybindUpdateOperation::Remove {
        target: settings::KeybindUpdateTarget {
            context: existing.context().and_then(KeybindContextString::local_str),
            keystrokes,
            action_name: existing.action().name,
            action_arguments: existing
                .action()
                .arguments
                .as_ref()
                .map(|arguments| arguments.text.as_ref()),
        },
        target_keybind_source: existing.keybind_source().unwrap_or(KeybindSource::User),

View on GitHub (pinned to 9d272b0363)

Solutions

  1. Only enable 'Remove keybinding' UI actions when the selected binding has keystrokes
  2. For bindings that live in the default keymap, add an overriding entry instead of removing
  3. Edit the user keymap.json directly (via keymap editor open-file) to delete the stale block
  4. Check whether the binding came from a bundled keymap that the removal flow cannot modify by design

Example fix

// before
let Some(keystrokes) = existing.keystrokes() else {
    anyhow::bail!("Cannot remove a keybinding that does not exist");
};

// after (caller gates the action)
let can_remove = existing.keystrokes().is_some();
// ... .when(can_remove, |row| row.mouse_listeners(...))
Defensive patterns

Strategy: validation

Validate before calling

let Some(keystrokes) = binding.keystrokes() else {
    // nothing to match in the keymap file; hide the remove affordance
    return Ok(());
};

Type guard

fn is_removable_binding(b: &ProcessedBinding) -> bool { b.keystrokes().is_some() }

Prevention

When it happens

Trigger: The remove flow invoked on a binding that carries no keystrokes — e.g. an action-only entry or a partially constructed binding object — so the KeybindUpdateOperation::Remove target would have nothing to match against in the JSON.

Common situations: UI race where the binding list was refreshed mid-edit; entries synthesized from defaults rather than user keymap contents; stale code paths calling remove on non-keystroke bindings.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of zed-industries/zed@9d272b0363 (2026-08-20). Data as JSON: /api/errors/8563a567249f8596. Report an issue: GitHub.