micro-editor/micro · warning

bindings is locked by the user

Error message

bindings is locked by the user

What it means

Returned by TryBindKeyPlug (internal/action/bindings.go:268) when the global setting "lockbindings" is true. This API is the plugin-facing binding entry point: it intentionally refuses to add or change keybindings while the user has locked them, so plugins cannot hijack keys. The error is a policy rejection, not a malfunction; TryBindKey (the user path) is unaffected.

Source

Thrown at internal/action/bindings.go:268

		if len(seq1.keys) != len(seq2.keys) {
			return false
		}
		for i := 0; i < len(seq1.keys); i++ {
			if seq1.keys[i] != seq2.keys[i] {
				return false
			}
		}
		return true
	}

	return e1 == e2
}

// TryBindKeyPlug tries to bind a key for the plugin without writing to bindings.json.
// This operation can be rejected by lockbindings to prevent unexpected actions by the user.
func TryBindKeyPlug(k, v string, overwrite bool) (bool, error) {
	if l, ok := config.GlobalSettings["lockbindings"]; ok && l.(bool) {
		return false, errors.New("bindings is locked by the user")
	}
	return TryBindKey(k, v, overwrite, false)
}

// TryBindKey tries to bind a key by writing to config.ConfigDir/bindings.json
// Returns true if the keybinding already existed or is binded successfully and a possible error
func TryBindKey(k, v string, overwrite bool, writeToFile bool) (bool, error) {
	var e error
	var parsed map[string]any

	filename := filepath.Join(config.ConfigDir, "bindings.json")
	createBindingsIfNotExist(filename)
	if _, e = os.Stat(filename); e == nil {
		input, err := os.ReadFile(filename)
		if err != nil {
			return false, errors.New("Error reading bindings.json file: " + err.Error())
		}

View on GitHub (pinned to 1c8b82b32e)

Solutions

  1. Set "lockbindings": false in ~/.config/micro/settings.json (or via > set lockbindings false) and reload the plugin
  2. If you are the plugin user, bind the plugin's keys yourself in bindings.json, which bypasses TryBindKeyPlug
  3. If you are the plugin author, check bindings lock before binding and surface a friendly notice instead of failing (see defense snippet)

Example fix

-- before (lua plugin init.lua)
bindings.TryBindKeyplug("F9", "filemanager.toggle", true)

-- after: tolerate a locked bindings map
local ok, err = pcall(bindings.TryBindKeyplug, "F9", "filemanager.toggle", true)
if not ok or err then
  messenger.Info("filemanager: bindings locked; map F9 manually")
end
Defensive patterns

Strategy: validation

Validate before calling

-- Lua plugin: honor the user's lock before attempting to bind
if config.GetGlobalOption("lockbindings") then
    messenger.Info("bindings locked by user; skipping key registration")
    return
end
bindings.TryBindKeyplug("F9", "myplugin.toggle", true)

Try / catch

-- Lua equivalent of try-catch
local ok, err = pcall(bindings.TryBindKeyplug, "F9", "myplugin.toggle", true)
if not ok or (err and tostring(err):find("locked", 1, true)) then
    messenger.Info("myplugin: keybinding skipped (lockbindings enabled)")
end

Prevention

When it happens

Trigger: settings.json contains "lockbindings": true and an installed Lua plugin calls bindings.TryBindKeyplug(...) during init or at runtime (e.g. filemanager, lsp-style plugins registering shortcuts). The call returns (false, this error) and no binding is created.

Common situations: User enabled lockbindings after plugin trouble, then updated/reinstalled plugins that re-register keys; sharing settings.json across machines where the plugin expectation differs; plugin authors testing without realizing the lock is global.

Related errors


AI-assisted analysis of micro-editor/micro@1c8b82b32e (2026-08-15). Data as JSON: /api/errors/722cb2747de61b79. Report an issue: GitHub.