{"record":{"id":"8fad8d281440c0ae","repo":"hasura/graphql-engine","slug":"cannot-read-global-config-from-file-env-w","errorCode":null,"errorMessage":"cannot read global config from file/env: %w","messagePattern":"cannot read global config from file/env: %w","errorType":"exception","errorClass":"errors.Error","httpStatus":null,"severity":"error","filePath":"cli/global_config.go","lineNumber":227,"sourceCode":"\n\treturn nil\n}\n\n// readGlobalConfig reads the configuration from global config file env vars,\n// through viper.\nfunc (ec *ExecutionContext) readGlobalConfig() error {\n\tvar op errors.Op = \"cli.ExecutionContext.readGlobalConfig\"\n\t// need to get existing viper because https://github.com/spf13/viper/issues/233\n\tv := viper.New()\n\tv.SetEnvPrefix(\"HASURA_GRAPHQL\")\n\tv.AutomaticEnv()\n\tv.SetConfigName(\"config\")\n\tv.AddConfigPath(ec.GlobalConfigDir)\n\tv.SetDefault(\"cli_environment\", DefaultEnvironment)\n\n\terr := v.ReadInConfig()\n\tif err != nil {\n\t\treturn errors.E(op, fmt.Errorf(\"cannot read global config from file/env: %w\", err))\n\t}\n\n\tif ec.GlobalConfig == nil {\n\t\tec.Logger.Debugf(\"global config is not pre-set, reading from current env\")\n\t\tec.GlobalConfig = &GlobalConfig{\n\t\t\tUUID:                   v.GetString(\"uuid\"),\n\t\t\tEnableTelemetry:        v.GetBool(\"enable_telemetry\"),\n\t\t\tShowUpdateNotification: v.GetBool(\"show_update_notification\"),\n\t\t\tCLIEnvironment:         Environment(v.GetString(\"cli_environment\")),\n\t\t}\n\t} else {\n\t\tec.Logger.Debugf(\"global config is pre-set to %#v\", ec.GlobalConfig)\n\t}\n\n\tec.Logger.Debugf(\"global config: uuid: %v\", ec.GlobalConfig.UUID)\n\tec.Logger.Debugf(\"global config: enableTelemetry: %v\", ec.GlobalConfig.EnableTelemetry)\n\tec.Logger.Debugf(\n\t\t\"global config: showUpdateNotification: %v\",","sourceCodeStart":209,"sourceCodeEnd":245,"githubUrl":"https://github.com/hasura/graphql-engine/blob/724551b9ae87845594ef0408cff0e50eb6c90dc5/cli/global_config.go#L209-L245","documentation":"readGlobalConfig uses viper to read config.yaml in ec.GlobalConfigDir plus environment overrides, and v.ReadInConfig() failed. Unlike 215, this covers viper-level failures: unreadable file (permissions on an existing config), unsupported/ambiguous config format for the discovered file, or env-var binding issues; a genuinely absent file is normally handled as NotFound elsewhere.","triggerScenarios":"GlobalConfigDir contains a config file that exists but cannot be opened (mode 000, ownership mismatch), has an extension viper cannot infer a format from, or global config was pre-set to nil while env vars referenced by SetDefault/bind fail to coerce.","commonSituations":"Root-created config files read by unprivileged users, a config file with an odd extension, stale viper cache of a deleted file, or env vars (CLI_ENVIRONMENT etc.) set to values that fail type coercion into config fields.","solutions":["Inspect the wrapped viper error: ConfigFileNotFoundError means path issues, *fs.PathError means permissions, IncompatibleConfigError means wrong types","Fix permissions/ownership of GlobalConfigDir/config.* so the running user can read it","Rename the config file to config.yaml (the name SetConfigName(\"config\") expects) and ensure a supported extension","Sanitize environment variables that override config values to valid types"],"exampleFix":"# before\n-rw------- 1 root root /root/.mycli/config.yaml\n# after\n$ sudo chmod 644 /root/.mycli/config.yaml","handlingStrategy":"validation","validationCode":"p := filepath.Join(ec.GlobalConfigDir, \"config.yaml\")\nif _, err := os.Stat(p); err == nil {\n    if f, err := os.Open(p); err != nil {\n        return fmt.Errorf(\"config exists but is unreadable: %w\", err)\n    }\n    _ = f.Close()\n}","typeGuard":"func configReadableAndNamed(dir string) bool {\n    p := filepath.Join(dir, \"config.yaml\")\n    f, err := os.Open(p)\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(), \"cannot read global config from file/env\") {\n        var pathErr *fs.PathError\n        if stderrors.As(err, &pathErr) {\n            _ = os.Chmod(ec.GlobalConfigDir+\"/config.yaml\", 0o644)\n            return ec.Prepare(ctx)\n        }\n    }\n    return err\n}","preventionTips":["Name the file exactly config.yaml with a supported extension","Ensure read permissions for the invoking user on dir and file","Keep env overrides type-compatible with config fields"],"tags":["go","viper","config","permissions","environment"],"backgroundTag":"config-file-read-failed","analyzedSha":"724551b9ae87845594ef0408cff0e50eb6c90dc5","analyzedAt":"2026-08-28T07:32:55.105Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}