{"record":{"id":"bd2b7250551d2fa6","repo":"temporalio/temporal","slug":"when-using-internal-frontend-publicclient-must-be","errorCode":null,"errorMessage":"when using internal-frontend, publicClient must be empty","messagePattern":"when using internal-frontend, publicClient must be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/config/config.go","lineNumber":706,"sourceCode":"const (\n\tForceTLSConfigAuto      = \"\"\n\tForceTLSConfigInternode = \"internode\"\n\tForceTLSConfigFrontend  = \"frontend\"\n)\n\n// Validate validates this config\nfunc (c *Config) Validate() error {\n\tif err := c.Persistence.Validate(); err != nil {\n\t\treturn err\n\t}\n\n\tif err := c.Archival.Validate(&c.NamespaceDefaults.Archival); err != nil {\n\t\treturn err\n\t}\n\n\t_, hasIFE := c.Services[string(primitives.InternalFrontendService)]\n\tif hasIFE && (c.PublicClient.HostPort != \"\" || c.PublicClient.ForceTLSConfig != \"\" || c.PublicClient.HTTPHostPort != \"\") {\n\t\treturn fmt.Errorf(\"when using internal-frontend, publicClient must be empty\")\n\t}\n\n\tswitch c.PublicClient.ForceTLSConfig {\n\tcase ForceTLSConfigAuto, ForceTLSConfigInternode, ForceTLSConfigFrontend:\n\tdefault:\n\t\treturn fmt.Errorf(\"invalid value for publicClient.forceTLSConfig: %q\", c.PublicClient.ForceTLSConfig)\n\t}\n\n\treturn nil\n}\n\n// String converts the config object into a string\nfunc (c *Config) String() string {\n\tvar buf bytes.Buffer\n\tencoder := yaml.NewEncoder(&buf)\n\tencoder.SetIndent(2)\n\t_ = encoder.Encode(c)\n\tmaskedYaml, _ := masker.MaskYaml(buf.String(), masker.DefaultYAMLFieldNames)","sourceCodeStart":688,"sourceCodeEnd":724,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/common/config/config.go#L688-L724","documentation":"This error comes from Config validation in temporal's config package. When the service set defines the internal-frontend service, the publicClient block must be fully omitted, because traffic intended for the public frontend is instead routed through the internal frontend; keeping a publicClient config is contradictory. Validation runs as part of config load/validate and aborts startup with this message.","triggerScenarios":"Calling (Config).Validate (via LoadConfig/load) when c.Services contains key \"internalFrontend\" (primitives.InternalFrontendService) while c.PublicClient.HostPort != \"\" OR c.PublicClient.ForceTLSConfig != \"\" OR c.PublicClient.HTTPPort/HTTPHostPort is set.","commonSituations":"Operators deploying temporal with the internal-frontend topology (self-hosted clusters fronting via internal frontend) copy a stock config that still has a publicClient section, or add internalFrontend to services without removing the previously used publicClient.HostPort/forceTLSConfig/httpTransport settings.","solutions":["Remove the entire publicClient block (hostPort, forceTLSConfig, httpHostPort) from the YAML config when internalFrontend is enabled","Remove the corresponding fields from the programmatically constructed common.Config struct","Re-run config load to confirm validation passes"],"exampleFix":"// before\nservices:\n  internalFrontend:\npublicClient:\n  hostPort: \"temporal.example.com:7233\"\n// after\nservices:\n  internalFrontend:\n# publicClient removed entirely","handlingStrategy":"validation","validationCode":"func hasPublicClientFields(c *config.Config) bool {\n\treturn c.PublicClient.HostPort != \"\" ||\n\t\tc.PublicClient.ForceTLSConfig != \"\" ||\n\t\tc.PublicClient.HTTPHostPort != \"\"\n}\n_, hasIFE := c.Services[string(primitives.InternalFrontendService)]\nif hasIFE && hasPublicClientFields(c) {\n\t// fix before calling Validate/LoadConfig: delete publicClient block\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When adding the internalFrontend service, always remove the publicClient section in the same change","Keep environment-specific config overlays free of publicClient unless the public frontend topology is used","Run config validation in CI to catch invalid service/publicClient combinations before deploy"],"tags":["config","validation","internal-frontend"],"backgroundTag":"invalid-config-value","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}