{"record":{"id":"a7b431b0c6b77740","repo":"hasura/graphql-engine","slug":"writing-global-config-file-failed-w","errorCode":null,"errorMessage":"writing global config file failed: %w","messagePattern":"writing global config file failed: %w","errorType":"exception","errorClass":"errors.Error","httpStatus":null,"severity":"error","filePath":"cli/global_config.go","lineNumber":194,"sourceCode":"\t\t// initialize the config object\n\t\tgc := rawGlobalConfig{}\n\n\t\terr := gc.read(ec.GlobalConfigFile)\n\t\tif err != nil {\n\t\t\treturn errors.E(op, fmt.Errorf(\"reading global config file failed: %w\", err))\n\t\t}\n\n\t\t// validate keys\n\t\terr = gc.validateKeys()\n\t\tif err != nil {\n\t\t\treturn errors.E(op, fmt.Errorf(\"validating global config file failed: %w\", err))\n\t\t}\n\n\t\t// write the file if there are any changes\n\t\tif gc.shoudlWrite {\n\t\t\terr := gc.write(ec.GlobalConfigFile)\n\t\t\tif err != nil {\n\t\t\t\treturn errors.E(op, fmt.Errorf(\"writing global config file failed: %w\", err))\n\t\t\t}\n\n\t\t\tec.Logger.Debugf(\n\t\t\t\t\"global config file written at '%s' with content '%+#v'\",\n\t\t\t\tec.GlobalConfigFile,\n\t\t\t\tgc,\n\t\t\t)\n\t\t}\n\t}\n\n\terr = ec.readGlobalConfig()\n\tif err != nil {\n\t\treturn errors.E(op, err)\n\t}\n\n\treturn nil\n}\n","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/hasura/graphql-engine/blob/724551b9ae87845594ef0408cff0e50eb6c90dc5/cli/global_config.go#L176-L212","documentation":"The existing config file was read and validated, but a migration/normalization set gc.shoudlWrite = true and the subsequent rewrite of the file failed with an I/O error. Same failure class as 210/214 (unwritable path, read-only FS, locked file) but on the rewrite-after-read path.","triggerScenarios":"Config file is readable but not writable (0644 root-owned while running as a normal user) exactly when the CLI needs to persist added/normalized keys, or the file is locked by another process on Windows.","commonSituations":"Configs deployed via configuration management as root-owned files, then executed by unprivileged users; read-only mounted config volumes; editors holding locks.","solutions":["chmod 644 + chown to the running user so the file is writable, or chmod 444->644","Make the config file byte-for-byte canonical (correct keys/format) so no rewrite is triggered","Mount the config volume read-write if it is currently read-only","Pre-apply migrations with a matching CLI version that can write the file"],"exampleFix":"# before\n-rw-r--r-- 1 root root ~/.mycli/config.yaml\n# after\n$ sudo chown $(id -u):$(id -g) ~/.mycli/config.yaml","handlingStrategy":"validation","validationCode":"if info, err := os.Stat(ec.GlobalConfigFile); err == nil {\n    if info.Mode().Perm()&0o200 == 0 {\n        return fmt.Errorf(\"config file %s is not writable; migrations will fail\", ec.GlobalConfigFile)\n    }\n}","typeGuard":"func fileIsWritable(p string) bool {\n    f, err := os.OpenFile(p, os.O_WRONLY, 0)\n    if err != nil {\n        return false\n    }\n    _ = f.Close()\n    return true\n}","tryCatchPattern":"if err := ec.Prepare(ctx); err != nil {\n    if strings.Contains(err.Error(), \"writing global config file failed\") {\n        _ = os.Chmod(ec.GlobalConfigFile, 0o644)\n        return ec.Prepare(ctx)\n    }\n    return err\n}","preventionTips":["Ensure config files deployed by config management remain writable by the run user","Keep config canonical so no migration rewrite is needed","Check for editor/process locks on Windows before runs"],"tags":["go","filesystem","permissions","config","migration"],"backgroundTag":"file-write-permission-denied","analyzedSha":"724551b9ae87845594ef0408cff0e50eb6c90dc5","analyzedAt":"2026-08-28T07:32:55.105Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}