{"record":{"id":"2bea61e7d3ec0ede","repo":"temporalio/temporal","slug":"global-authorization-remoteclusterauth-require-is","errorCode":null,"errorMessage":"global.authorization.remoteClusterAuth.require is true but no TokenProvider is configured: use WithTokenProvider","messagePattern":"global\\.authorization\\.remoteClusterAuth\\.require is true but no TokenProvider is configured: use WithTokenProvider","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"temporal/fx.go","lineNumber":298,"sourceCode":"\t\tesClient, err = esclient.NewClient(esConfig, esHttpClient, logger)\n\t\tif err != nil {\n\t\t\treturn serverOptionsProvider{}, fmt.Errorf(\"unable to create Elasticsearch client (URL = %v, username = %q): %w\",\n\t\t\t\tesConfig.URL.Redacted(), esConfig.Username, err)\n\t\t}\n\t}\n\n\t// check that when static hosts are defined, they are defined for all required hosts\n\tif len(so.hostsByService) > 0 {\n\t\tfor _, service := range DefaultServices {\n\t\t\thosts := so.hostsByService[primitives.ServiceName(service)]\n\t\t\tif len(hosts.All) == 0 {\n\t\t\t\treturn serverOptionsProvider{}, fmt.Errorf(\"%w: %v\", missingServiceInStaticHosts, service)\n\t\t\t}\n\t\t}\n\t}\n\n\tif so.config.Global.Authorization.RemoteClusterAuth.Require && so.tokenProvider == nil {\n\t\treturn serverOptionsProvider{}, errors.New(\"global.authorization.remoteClusterAuth.require is true but no TokenProvider is configured: use WithTokenProvider\")\n\t}\n\t// TokenCredentials require TLS (RFC 9700); without a remote-cluster TLS source the first\n\t// cross-cluster dial would fatal-log, with no clear \"you forgot TLS\" diagnostic.\n\t// Coarse check: any remote-cluster TLS entry passes; per-hostname config is still validated\n\t// lazily on first dial.\n\tif so.tokenProvider != nil && so.tlsConfigProvider == nil && len(so.config.Global.TLS.RemoteClusters) == 0 {\n\t\treturn 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\")\n\t}\n\n\treturn serverOptionsProvider{\n\t\tServerOptions:              so,\n\t\tStopChan:                   stopChan,\n\t\tStartupSynchronizationMode: so.startupSynchronizationMode,\n\n\t\tConfig:      so.config,\n\t\tPProfConfig: &so.config.Global.PProf,\n\t\tLogConfig:   so.config.Log,\n","sourceCodeStart":280,"sourceCodeEnd":316,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/temporal/fx.go#L280-L316","documentation":"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.","triggerScenarios":"Programmatically building server options with config requiring remote cluster auth (Global.Authorization.RemoteClusterAuth.Require == true) while never calling WithTokenProvider on the options builder.","commonSituations":"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.","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"],"exampleFix":"// before\nserver := temporal.NewServerFxdist(..., temporal.WithConfig(cfg)) // no token provider\n// after\nserver := temporal.NewServerFxdist(...,\n    temporal.WithConfig(cfg),\n    temporal.WithTokenProvider(myTokenProvider),\n)","handlingStrategy":"validation","validationCode":"func validateRemoteAuth(cfg *config.Config, opts []temporal.ServerOption) error {\n    if cfg.Global.Authorization.RemoteClusterAuth.Require {\n        for _, o := range opts {\n            if _, ok := o.(temporal.TokenProviderOption); ok { return nil }\n        }\n        return errors.New(\"remoteClusterAuth.require is on: pass WithTokenProvider\")\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"provider, err := temporal.ServerOptionsProvider(...)\nif err != nil {\n    if strings.Contains(err.Error(), \"no TokenProvider is configured\") {\n        return fmt.Errorf(\"bootstrap: attach a token provider for remote cluster auth: %w\", err)\n    }\n    return err\n}","preventionTips":["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"],"tags":["temporal-server","authorization","remote-cluster","config"],"backgroundTag":"missing-token-provider","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}