{"record":{"id":"761f18fb277c9f6d","repo":"micro-editor/micro","slug":"error-reading-bindings-json-file-s","errorCode":null,"errorMessage":"Error reading bindings.json file: %s","messagePattern":"Error reading bindings\\.json file: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/action/bindings.go","lineNumber":284,"sourceCode":"func 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\n\t\terr = json5.Unmarshal(input, &parsed)\n\t\tif err != nil {\n\t\t\treturn false, errors.New(\"Error reading bindings.json: \" + err.Error())\n\t\t}\n\n\t\tkey, err := findEvent(k)\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\n\t\tfound := false\n\t\tvar ev string\n\t\tfor ev = range parsed {\n\t\t\tif e, err := findEvent(ev); err == nil {\n\t\t\t\tif eventsEqual(e, key) {\n\t\t\t\t\tfound = true","sourceCodeStart":266,"sourceCodeEnd":302,"githubUrl":"https://github.com/micro-editor/micro/blob/1c8b82b32e408a5faf340039ed92d5266bea3293/internal/action/bindings.go#L266-L302","documentation":"Returned by TryBindKey (internal/action/bindings.go:284) when os.Stat says bindings.json exists but os.ReadFile then fails. The stat-succeeds/read-fails window means an I/O problem rather than a missing file: permission denied on the file or a config directory, the file being replaced by a directory between calls, or flaky media. The raw OS error is appended for diagnosis.","triggerScenarios":"Executing > bind ... when bindings.json is unreadable: mode 000, owned by another user (classic after running micro once with sudo), a directory named bindings.json, or a read-only/filesystem-full home.","commonSituations":"Ran 'sudo micro' for one root-owned edit, leaving root-owned ~/.config/micro/bindings.json; home on NFS with permission mapping; disk quota exhausted so read syscalls fail.","solutions":["Fix ownership/perms: sudo chown -R $USER: ~/.config/micro && chmod 644 ~/.config/micro/bindings.json","If bindings.json is somehow a directory: rm -rf ~/.config/micro/bindings.json and let micro recreate it ('{}')","Check filesystem health: df -h ~ and dmesg | tail for I/O errors; remount a read-only home rw","As a last resort move the file away: mv bindings.json bindings.json.broken (createBindingsIfNotExist writes a fresh '{}')"],"exampleFix":"// before: bindings.json owned by root after 'sudo micro'\n$ ls -l ~/.config/micro/bindings.json\n-rw------- 1 root root 542 ... bindings.json\n> bind CtrlQ QuitAll  ->  Error reading bindings.json file: ... permission denied\n\n// after\n$ sudo chown $USER:$USER ~/.config/micro/bindings.json\n$ chmod 644 ~/.config/micro/bindings.json","handlingStrategy":"validation","validationCode":"// Ensure bindings.json is readable before any bind call\nfunc bindingsReadable() error {\n    p := filepath.Join(config.ConfigDir, \"bindings.json\")\n    fi, err := os.Stat(p)\n    if err != nil { return err }\n    if !fi.Mode().IsRegular() { return fmt.Errorf(\"%s is not a regular file\", p) }\n    f, err := os.Open(p)\n    if err != nil { return err } // surfaces permission errors early\n    return f.Close()\n}","typeGuard":null,"tryCatchPattern":"if _, err := action.TryBindKey(k, v, true, true); err != nil {\n    if strings.HasPrefix(err.Error(), \"Error reading bindings.json file\") {\n        // permissions/IO: prompt the user to fix ownership instead of retrying\n        return fmt.Errorf(\"fix permissions on bindings.json: %w\", err)\n    }\n    return err\n}","preventionTips":["Avoid 'sudo micro'; if unavoidable, chown -R $USER ~/.config/micro afterwards","Back up ~/.config/micro before OS migrations that change UIDs","Watch for the stat-ok/read-fail signature: it almost always means ownership or mode"],"tags":["config","permissions","io","filesystem","keybinding"],"backgroundTag":null,"analyzedSha":"1c8b82b32e408a5faf340039ed92d5266bea3293","analyzedAt":"2026-08-15T20:01:45.134Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}