{"record":{"id":"b6d3e5fd67a67aa8","repo":"temporalio/temporal","slug":"could-not-read-config-file-s-error-w","errorCode":null,"errorMessage":"could not read config file: %s. error: %w","messagePattern":"could not read config file: (.+?)\\. error: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/config/loader.go","lineNumber":220,"sourceCode":"\t\tprocessedData, err := processConfigFile(data, filepath.Base(f))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\terr = yaml.Unmarshal(processedData, config)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tvalidate := newValidator()\n\treturn validate.Validate(config)\n}\n\nfunc readConfigFile(path string) ([]byte, error) {\n\tdata, err := os.ReadFile(path)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"could not read config file: %s. error: %w\", path, err)\n\n\t}\n\treturn data, nil\n}\n\n// processConfigFile processes a config file, rendering it as a template if enabled\nfunc processConfigFile(data []byte, filename string) ([]byte, error) {\n\t// If the config file contains \"enable-template\" in a comment within the first 1KB, then\n\t// we will treat the file as a template and render it.\n\ttemplating, err := checkTemplatingEnabled(data)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif !templating {\n\t\treturn data, nil\n\t}\n","sourceCodeStart":202,"sourceCodeEnd":238,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/common/config/loader.go#L202-L238","documentation":"readConfigFile wraps os.ReadFile failures for an individual config file, including the path and underlying OS error. Config load fails fast: once the file list is known, every file must be readable to build the full Config. This is distinct from parse errors — the file exists in the list but its bytes could not be read.","triggerScenarios":"load or loadLegacy -> readConfigFile(path) when the file listed by getConfigFiles disappears, is a directory, or lacks read permission; also symlinks pointing to nonexistent targets.","commonSituations":"Broken symlink in the config dir, a config file deleted/renamed between listing and reading (races in k8s ConfigMap mounts), read-permission denied for the process user, or a zone-specific file left as a directory by mistake.","solutions":["Inspect the embedded OS error (error: %w) — e.g. permission denied vs no such file — and fix accordingly","chmod/chown the file so the temporal process user can read it","If the file is a broken symlink or directory, restore or remove it","In Kubernetes, verify the ConfigMap volume mount actually materialized the expected files"],"exampleFix":"// before\n$ ls -l /etc/temporal/config/production.yaml\nlrwxrwxrwx ... production.yaml -> /mnt/missing/production.yaml\n// after\n$ rm production.yaml\n$ kubectl create configmap temporal-config --from-file=config/","handlingStrategy":"validation","validationCode":"func canRead(path string) error {\n\tf, err := os.Open(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn f.Close()\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer real files over dangling symlinks in config dirs","Watch for races with ConfigMap/Secret volume updates; retry load on transient read errors if applicable","Run temporal under a user with read access to the mounted config files"],"tags":["config","filesystem","permissions"],"backgroundTag":"config-file-unreadable","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}