temporalio/temporal · error
failed to get config files: %w
Error message
failed to get config files: %w
What it means
loadLegacy in the config loader gathers the ordered list of YAML files (base, env, zone overlays) via getConfigFiles. If listing/reading the config directory fails (e.g. stat/read errors or malformed pattern), the error is wrapped as "failed to get config files" and config loading aborts. This means temporal could not even determine which config files exist, before parsing any of them.
Source
Thrown at common/config/loader.go:191
//
// base.yaml
// env.yaml -- where "environment" is one of the input parameters (e.g., "development")
// env_az.yaml -- where "zone" is another input parameter
func (opts *loadOptions) loadLegacy(config any) error {
stdlog.Printf("Loading config; env=%v,zone=%v,configDir=%v\n", opts.env, opts.zone, opts.configDir)
if opts.env == "" {
opts.env = envDevelopment
}
if opts.configDir == "" {
opts.configDir = defaultConfigDir
}
stdlog.Printf("Loading config; env=%v,zone=%v,configDir=%v\n", opts.env, opts.zone, opts.configDir)
files, err := getConfigFiles(opts.env, opts.configDir, opts.zone)
if err != nil {
return fmt.Errorf("failed to get config files: %w", err)
}
stdlog.Printf("Loading config files=%v\n", files)
for _, f := range files {
data, err := readConfigFile(f)
if err != nil {
return err
}
processedData, err := processConfigFile(data, filepath.Base(f))
if err != nil {
return err
}
err = yaml.Unmarshal(processedData, config)
if err != nil {
return errView on GitHub (pinned to bde624efd1)
Solutions
- Verify the config directory path (configDir option / CONFIG_PATH env) exists and is readable by the temporal process
- Ensure config files follow the expected naming: base config, then env (and zone) files, e.g. development.yaml or production.yaml under the configured dir
- Fix filesystem permissions (chown/chmod) or remount the config volume
- Check the wrapped underlying error (%w) for the exact OS reason (no such file, permission denied, etc.)
Example fix
// before (cmd flag) --config-dir /etc/temporal/confg # typo // after --config-dir /etc/temporal/config
Defensive patterns
Strategy: validation
Validate before calling
if info, err := os.Stat(configDir); err != nil || !info.IsDir() {
return fmt.Errorf("config dir %s missing or not a directory: %w", configDir, err)
} Prevention
- Verify the config dir exists in the deployment (volume mounts, image build) before startup
- Standardize CONFIG_PATH across environments; fail fast with a readiness check
- Mount config read-only and ensure the process user has traverse/read permissions
When it happens
Trigger: Calling LoadConfig/load -> loadLegacy with a configDir that does not exist, is unreadable (permissions), or where getConfigFiles encounters an OS error while resolving env/zone file paths.
Common situations: Wrong CONFIG_PATH/env var pointing at a missing directory, container image missing the /etc/temporal/config mount, permission denied after running as a non-root user, or typo'd configDir flag/zone name causing expected file paths to be unresolvable.
Related errors
- missing current cluster metadata under clusterMetadata.Clust
- unable to read client ca file
- unable to read client certificate file
- could not read config file: %s. error: %w
- unable to create metrics handler: %w
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/7d32e80aeb88ea4b.
Report an issue: GitHub.