temporalio/temporal · error
env, config, zone can not be set if configFilePath is set
Error message
env, config, zone can not be set if configFilePath is set
What it means
loadConfig refuses to combine configFilePath with env, configDir ("config"), or zone settings. Loading a single explicit file is mutually exclusive with directory/env/zone-based config resolution, so this guard prevents ambiguous configuration sources and returns this validation error from loadAndValidate.
Source
Thrown at temporal/server_options.go:109
if so.config == nil {
err := so.loadConfig()
if err != nil {
return fmt.Errorf("unable to load config: %w", err)
}
}
err := so.validateConfig()
if err != nil {
return fmt.Errorf("config validation error: %w", err)
}
return nil
}
func (so *serverOptions) loadConfig() error {
if so.configFilePath != "" {
if so.env != "" || so.configDir != "" || so.zone != "" {
return errors.New("env, config, zone can not be set if configFilePath is set")
}
cfg, err := config.Load(
config.WithConfigFile(so.configFilePath),
)
if err != nil {
return fmt.Errorf("could not load config file: %w", err)
}
so.config = cfg
return nil
}
cfg, err := config.Load(
config.WithEnv(so.env),
config.WithConfigDir(so.configDir),
config.WithZone(so.zone),
)
if err != nil {
return fmt.Errorf("could not load config file: %w", err)
}View on GitHub (pinned to bde624efd1)
Solutions
- Unset env/configDir/zone (clear TEMPORAL_ENV / TEMPORAL_CONFIG_DIR and --env/--zone flags) when using configFilePath
- Or drop configFilePath and rely on env/configDir/zone resolution instead
- In code, choose one mode: either config.WithConfigFile(...) or config.WithEnv/WithConfigDir/WithZone
- Wrap config loading so conflicting sources are detected and reported with which flags collided
Example fix
// before
opts := temporal.NewServerOptions(
temporal.WithConfigFilePath("/etc/temporal/config.yaml"),
temporal.WithEnv("prod"), // conflicts
)
// after
opts := temporal.NewServerOptions(
temporal.WithConfigFilePath("/etc/temporal/config.yaml"),
) Defensive patterns
Strategy: validation
Validate before calling
func pickConfigSource(env, zone, configDir, configFilePath string) (string, error) {
var set []string
if env != "" { set = append(set, "env") }
if configDir != "" { set = append(set, "configDir") }
if zone != "" { set = append(set, "zone") }
if configFilePath != "" { set = append(set, "configFilePath") }
if configFilePath != "" && len(set) > 1 {
return "", fmt.Errorf("configFilePath cannot be combined with: %v", set[:len(set)-1])
}
return configFilePath, nil
} Try / catch
if err := so.loadAndValidate(); err != nil {
if strings.Contains(err.Error(), "env, config, zone can not be set if configFilePath") {
return fmt.Errorf("clear env/config-dir/zone flags or drop --config: %w", err)
}
return err
} Prevention
- In containers, decide on one config mechanism and document it; don't bake env vars AND mount a file
- In CLI wrappers, mutually exclude --config with --env/--zone flags before invoking
- Inspect the environment (TEMPORAL_ENV, TEMPORAL_CONFIG_DIR) before defaulting to configFilePath
When it happens
Trigger: Calling server option loaders (NewServerOptions/NewConfig etc., or the CLI) with both a config file path and env/config-dir/zone set — e.g. ENVIRONMENT=prod TEMPORAL_CONFIG_DIR=... plus --config /path/to/config.yaml, or code setting so.configFilePath and so.env together.
Common situations: Container images with env-based config baked in, then a user mounts/passes an explicit config file; CLI invocations mixing --env flags with --config; scripts exporting TEMPORAL_ENV while also pointing at a file.
Related errors
- config validation error: %w
- %q service is missing in config
- missing current cluster metadata under clusterMetadata.Clust
- hosts are missing in static hosts for service: ${service}
- global.authorization.remoteClusterAuth.require is true but n
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/3ba28bcf03ec2952.
Report an issue: GitHub.