{"record":{"id":"e9b3e355a3144d00","repo":"bcicen/ctop","slug":"failed-to-open-config-for-writing-s","errorCode":null,"errorMessage":"failed to open config for writing: %s","messagePattern":"failed to open config for writing: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"config/file.go","lineNumber":103,"sourceCode":"\tcfgdir := filepath.Dir(path)\n\t// create config dir if not exist\n\tif _, err := os.Stat(cfgdir); err != nil {\n\t\terr = os.MkdirAll(cfgdir, 0755)\n\t\tif err != nil {\n\t\t\treturn path, fmt.Errorf(\"failed to create config dir [%s]: %s\", cfgdir, err)\n\t\t}\n\t}\n\n\t// remove prior to writing new file\n\tif err := os.Remove(path); err != nil {\n\t\tif !os.IsNotExist(err) {\n\t\t\treturn path, err\n\t\t}\n\t}\n\n\tfile, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0644)\n\tif err != nil {\n\t\treturn path, fmt.Errorf(\"failed to open config for writing: %s\", err)\n\t}\n\n\twriter := toml.NewEncoder(file)\n\terr = writer.Encode(exportConfig())\n\tif err != nil {\n\t\treturn path, fmt.Errorf(\"failed to write config: %s\", err)\n\t}\n\n\treturn path, nil\n}\n\n// determine config path from environment\nfunc getConfigPath() (path string, err error) {\n\thomeDir, ok := os.LookupEnv(\"HOME\")\n\tif !ok {\n\t\treturn path, fmt.Errorf(\"$HOME not set\")\n\t}\n","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/bcicen/ctop/blob/59f00dd6aaebf48f3bc501e174f75f815c2619f0/config/file.go#L85-L121","documentation":"config.Write opens the config file with os.OpenFile(O_RDWR|O_CREATE, 0644) before encoding TOML. If the file cannot be opened, the error is wrapped with the path context as 'failed to open config for writing'.","triggerScenarios":"os.OpenFile fails: directory doesn't exist or isn't writable, path is a directory, or permission denied on an existing config file.","commonSituations":"Config file owned by another user (created under sudo); config path is a directory; stale permissions after switching users or running in a container as a different UID.","solutions":["Fix file/directory permissions on the config path (chmod 0644 file, writable dir)","Remove or rename an invalid file sitting at the config path","Run without sudo or chown the config back to the current user"],"exampleFix":"// before\n-rw------- root root config.toml   # app runs as non-root\n// after\nchown $USER config.toml && chmod 0644 config.toml","handlingStrategy":"try-catch","validationCode":"if fi, err := os.Stat(path); err == nil && fi.IsDir() { /* path invalid: it's a directory */ }\nif fi, err := os.Stat(path); err == nil { f, e := os.OpenFile(path, os.O_WRONLY, 0644); if e != nil { /* fix perms */ } else { f.Close() } }","typeGuard":null,"tryCatchPattern":"_, err := config.Write()\nif err != nil && strings.HasPrefix(err.Error(), \"failed to open config for writing\") {\n    // correct file ownership/permissions and retry\n}","preventionTips":["Keep config file perms 0644 and owned by the running user","Never point the config path at a directory","Avoid running the app under sudo (creates root-owned files)"],"tags":["filesystem","permissions","config"],"backgroundTag":"file-open-permission-denied","analyzedSha":"59f00dd6aaebf48f3bc501e174f75f815c2619f0","analyzedAt":"2026-09-02T23:34:03.832Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}