temporalio/temporal · error
global.authorization.remoteClusterAuth.require is true but n
Error message
global.authorization.remoteClusterAuth.require is true but no TokenProvider is configured: use WithTokenProvider
What it means
ServerOptionsProvider validates remote-cluster authorization settings at server construction. If global.authorization.remoteClusterAuth.require is enabled, a TokenProvider must be registered via WithTokenProvider; otherwise cross-cluster requests cannot be authenticated, so the provider fails fast with this error.
Source
Thrown at temporal/fx.go:298
esClient, err = esclient.NewClient(esConfig, esHttpClient, logger)
if err != nil {
return serverOptionsProvider{}, fmt.Errorf("unable to create Elasticsearch client (URL = %v, username = %q): %w",
esConfig.URL.Redacted(), esConfig.Username, err)
}
}
// check that when static hosts are defined, they are defined for all required hosts
if len(so.hostsByService) > 0 {
for _, service := range DefaultServices {
hosts := so.hostsByService[primitives.ServiceName(service)]
if len(hosts.All) == 0 {
return serverOptionsProvider{}, fmt.Errorf("%w: %v", missingServiceInStaticHosts, service)
}
}
}
if so.config.Global.Authorization.RemoteClusterAuth.Require && so.tokenProvider == nil {
return serverOptionsProvider{}, errors.New("global.authorization.remoteClusterAuth.require is true but no TokenProvider is configured: use WithTokenProvider")
}
// TokenCredentials require TLS (RFC 9700); without a remote-cluster TLS source the first
// cross-cluster dial would fatal-log, with no clear "you forgot TLS" diagnostic.
// Coarse check: any remote-cluster TLS entry passes; per-hostname config is still validated
// lazily on first dial.
if so.tokenProvider != nil && so.tlsConfigProvider == nil && len(so.config.Global.TLS.RemoteClusters) == 0 {
return serverOptionsProvider{}, errors.New("WithTokenProvider is set but no remote-cluster TLS is configured: supply global.tls.remoteClusters in config, or pass a provider via WithTLSConfigProvider")
}
return serverOptionsProvider{
ServerOptions: so,
StopChan: stopChan,
StartupSynchronizationMode: so.startupSynchronizationMode,
Config: so.config,
PProfConfig: &so.config.Global.PProf,
LogConfig: so.config.Log,
View on GitHub (pinned to bde624efd1)
Solutions
- Call WithTokenProvider(...) with an implementation that returns valid tokens when building server options
- If remote cluster auth is not needed, set global.authorization.remoteClusterAuth.require to false in config
- Review the fx boot logs for the wrapped error to confirm which service bootstrap failed
- Add a startup test asserting the options provider builds successfully with your production config
Example fix
// before
server := temporal.NewServerFxdist(..., temporal.WithConfig(cfg)) // no token provider
// after
server := temporal.NewServerFxdist(...,
temporal.WithConfig(cfg),
temporal.WithTokenProvider(myTokenProvider),
) Defensive patterns
Strategy: validation
Validate before calling
func validateRemoteAuth(cfg *config.Config, opts []temporal.ServerOption) error {
if cfg.Global.Authorization.RemoteClusterAuth.Require {
for _, o := range opts {
if _, ok := o.(temporal.TokenProviderOption); ok { return nil }
}
return errors.New("remoteClusterAuth.require is on: pass WithTokenProvider")
}
return nil
} Try / catch
provider, err := temporal.ServerOptionsProvider(...)
if err != nil {
if strings.Contains(err.Error(), "no TokenProvider is configured") {
return fmt.Errorf("bootstrap: attach a token provider for remote cluster auth: %w", err)
}
return err
} Prevention
- Whenever enabling remoteClusterAuth.require in config, pair it with WithTokenProvider in server bootstrap code
- Add an options-provider smoke test to CI using production config
- Document the WithTokenProvider requirement next to the config flag
When it happens
Trigger: Programmatically building server options with config requiring remote cluster auth (Global.Authorization.RemoteClusterAuth.Require == true) while never calling WithTokenProvider on the options builder.
Common situations: Enabling remoteClusterAuth.require in temporal.yaml for cross-cluster (multi-region/replication) setups but forgetting the token provider in embedded-server code; copying server bootstrap code from a single-cluster example into an authorized multi-cluster deployment.
Related errors
- WithTokenProvider is set but no remote-cluster TLS is config
- missing current cluster metadata under clusterMetadata.Clust
- hosts are missing in static hosts for service: ${service}
- env, config, zone can not be set if configFilePath is set
- unable to load config: %w
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/2bea61e7d3ec0ede.
Report an issue: GitHub.