{"record":{"id":"a0e80c530268ef25","repo":"hasura/graphql-engine","slug":"cannot-create-global-config-directory-w","errorCode":null,"errorMessage":"cannot create global config directory: %w","messagePattern":"cannot create global config directory: %w","errorType":"exception","errorClass":"errors.Error","httpStatus":null,"severity":"error","filePath":"cli/global_config.go","lineNumber":132,"sourceCode":"\tvar op errors.Op = \"cli.ExecutionContext.setupGlobalConfig\"\n\t// check if the directory name is set, else default\n\tif len(ec.GlobalConfigDir) == 0 {\n\t\tec.Logger.Debug(\"global config directory is not pre-set, defaulting\")\n\n\t\thome, err := os.UserHomeDir()\n\t\tif err != nil {\n\t\t\treturn errors.E(op, fmt.Errorf(\"cannot get home directory: %w\", err))\n\t\t}\n\n\t\tglobalConfigDir := filepath.Join(home, GlobalConfigDirName)\n\t\tec.GlobalConfigDir = globalConfigDir\n\t\tec.Logger.Debugf(\"global config directory set as '%s'\", ec.GlobalConfigDir)\n\t}\n\n\t// create the config directory\n\terr := os.MkdirAll(ec.GlobalConfigDir, os.ModePerm)\n\tif err != nil {\n\t\treturn errors.E(op, fmt.Errorf(\"cannot create global config directory: %w\", err))\n\t}\n\n\t// check if the filename is set, else default\n\tif len(ec.GlobalConfigFile) == 0 {\n\t\tec.GlobalConfigFile = filepath.Join(ec.GlobalConfigDir, GlobalConfigFileName)\n\t\tec.Logger.Debugf(\"global config file set as '%s'\", ec.GlobalConfigFile)\n\t}\n\n\t// check if the global config file exist\n\t_, err = os.Stat(ec.GlobalConfigFile)\n\tif stderrors.Is(err, fs.ErrNotExist) {\n\t\t// file does not exist, teat as first run and create it\n\t\tec.Logger.Debug(\n\t\t\t\"global config file does not exist, this could be the first run, creating it...\",\n\t\t)\n\n\t\t// create an empty config object\n\t\tgc := &rawGlobalConfig{}","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/hasura/graphql-engine/blob/724551b9ae87845594ef0408cff0e50eb6c90dc5/cli/global_config.go#L114-L150","documentation":"os.MkdirAll(ec.GlobalConfigDir, os.ModePerm) failed while creating the global config directory. This wraps mkdir syscall errors: permission denied on a parent, a path component that exists as a file (ENOTDIR), read-only filesystem, or I/O errors. It fires for both the default (~/.<name>) and any custom GlobalConfigDir.","triggerScenarios":"GlobalConfigDir points under a root-owned path while running unprivileged, a path component (e.g. ~/.config) is actually a regular file, or the filesystem is read-only (immutable container, squashfs).","commonSituations":"Running the CLI as non-root against /etc/... paths, leftover files where directories are expected, read-only rootfs in Kubernetes, or SELinux/AppArmor denying mkdir.","solutions":["Manually create the directory with correct ownership: mkdir -p + chown","Check that no path component is a regular file (ls -la each level) and remove/rename it","Point GlobalConfigDir at a writable location if the filesystem is read-only","Run with sufficient privileges or fix SELinux/AppArmor labels if enforced"],"exampleFix":"// before\nec.GlobalConfigDir = \"/etc/mycli\"\n// after\nec.GlobalConfigDir = filepath.Join(os.Getenv(\"HOME\"), \".mycli\")","handlingStrategy":"validation","validationCode":"if err := os.MkdirAll(ec.GlobalConfigDir, 0o755); err != nil {\n    return fmt.Errorf(\"cannot pre-create config dir %s: %w\", ec.GlobalConfigDir, err)\n}","typeGuard":"func dirIsCreatable(p string) bool {\n    return os.MkdirAll(p, 0o755) == nil\n}","tryCatchPattern":"if err := ec.Prepare(ctx); err != nil {\n    if strings.Contains(err.Error(), \"cannot create global config directory\") {\n        ec.GlobalConfigDir = filepath.Join(os.TempDir(), GlobalConfigDirName)\n        return ec.Prepare(ctx)\n    }\n    return err\n}","preventionTips":["Pre-create and own the config directory during installation","Never place GlobalConfigDir under paths owned by root when running unprivileged","Validate no path component is an existing regular file"],"tags":["go","filesystem","permissions","mkdir","config"],"backgroundTag":"directory-create-permission-denied","analyzedSha":"724551b9ae87845594ef0408cff0e50eb6c90dc5","analyzedAt":"2026-08-28T07:32:55.105Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}