{"record":{"id":"722cb2747de61b79","repo":"micro-editor/micro","slug":"bindings-is-locked-by-the-user","errorCode":null,"errorMessage":"bindings is locked by the user","messagePattern":"bindings is locked by the user","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/action/bindings.go","lineNumber":268,"sourceCode":"\t\tif len(seq1.keys) != len(seq2.keys) {\n\t\t\treturn false\n\t\t}\n\t\tfor i := 0; i < len(seq1.keys); i++ {\n\t\t\tif seq1.keys[i] != seq2.keys[i] {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\t}\n\n\treturn e1 == e2\n}\n\n// TryBindKeyPlug tries to bind a key for the plugin without writing to bindings.json.\n// This operation can be rejected by lockbindings to prevent unexpected actions by the user.\nfunc TryBindKeyPlug(k, v string, overwrite bool) (bool, error) {\n\tif l, ok := config.GlobalSettings[\"lockbindings\"]; ok && l.(bool) {\n\t\treturn false, errors.New(\"bindings is locked by the user\")\n\t}\n\treturn TryBindKey(k, v, overwrite, false)\n}\n\n// TryBindKey tries to bind a key by writing to config.ConfigDir/bindings.json\n// Returns true if the keybinding already existed or is binded successfully and a possible error\nfunc TryBindKey(k, v string, overwrite bool, writeToFile bool) (bool, error) {\n\tvar e error\n\tvar parsed map[string]any\n\n\tfilename := filepath.Join(config.ConfigDir, \"bindings.json\")\n\tcreateBindingsIfNotExist(filename)\n\tif _, e = os.Stat(filename); e == nil {\n\t\tinput, err := os.ReadFile(filename)\n\t\tif err != nil {\n\t\t\treturn false, errors.New(\"Error reading bindings.json file: \" + err.Error())\n\t\t}\n","sourceCodeStart":250,"sourceCodeEnd":286,"githubUrl":"https://github.com/micro-editor/micro/blob/1c8b82b32e408a5faf340039ed92d5266bea3293/internal/action/bindings.go#L250-L286","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Set \"lockbindings\": false in ~/.config/micro/settings.json (or via > set lockbindings false) and reload the plugin","If you are the plugin user, bind the plugin's keys yourself in bindings.json, which bypasses TryBindKeyPlug","If you are the plugin author, check bindings lock before binding and surface a friendly notice instead of failing (see defense snippet)"],"exampleFix":"-- before (lua plugin init.lua)\nbindings.TryBindKeyplug(\"F9\", \"filemanager.toggle\", true)\n\n-- after: tolerate a locked bindings map\nlocal ok, err = pcall(bindings.TryBindKeyplug, \"F9\", \"filemanager.toggle\", true)\nif not ok or err then\n  messenger.Info(\"filemanager: bindings locked; map F9 manually\")\nend","handlingStrategy":"validation","validationCode":"-- Lua plugin: honor the user's lock before attempting to bind\nif config.GetGlobalOption(\"lockbindings\") then\n    messenger.Info(\"bindings locked by user; skipping key registration\")\n    return\nend\nbindings.TryBindKeyplug(\"F9\", \"myplugin.toggle\", true)","typeGuard":null,"tryCatchPattern":"-- Lua equivalent of try-catch\nlocal ok, err = pcall(bindings.TryBindKeyplug, \"F9\", \"myplugin.toggle\", true)\nif not ok or (err and tostring(err):find(\"locked\", 1, true)) then\n    messenger.Info(\"myplugin: keybinding skipped (lockbindings enabled)\")\nend","preventionTips":["Document that your plugin binds keys and how lockbindings suppresses it","Offer a manual snippet users can paste into bindings.json instead","Never retry in a loop when the lock error arrives — it's a deliberate policy"],"tags":["plugin","lua","settings","keybinding","policy"],"backgroundTag":null,"analyzedSha":"1c8b82b32e408a5faf340039ed92d5266bea3293","analyzedAt":"2026-08-15T20:01:45.134Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}