{"record":{"id":"20e338a815c7dd0d","repo":"kubernetes/kops","slug":"discoveryservice-url-must-be-specified","errorCode":null,"errorMessage":"discoveryService URL must be specified","messagePattern":"discoveryService URL must be specified","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/model/components/discovery.go","lineNumber":83,"sourceCode":"\t\t\t\tserviceAccountIssuer, err = base.GetHTTPsUrl()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\tcase *vfs.MemFSPath:\n\t\t\t\tif !base.IsClusterReadable() {\n\t\t\t\t\t// If this _is_ a test, we should call MarkClusterReadable\n\t\t\t\t\treturn fmt.Errorf(\"locationStore=%q is only supported in tests\", store)\n\t\t\t\t}\n\t\t\t\tserviceAccountIssuer = strings.Replace(base.Path(), \"memfs://\", \"https://\", 1)\n\t\t\tdefault:\n\t\t\t\treturn fmt.Errorf(\"locationStore=%q is of unexpected type %T\", store, base)\n\t\t\t}\n\t\t} else if said != nil && said.DiscoveryService != nil {\n\t\t\tdiscoveryService := said.DiscoveryService\n\n\t\t\tserviceAccountIssuer = discoveryService.URL\n\t\t\tif serviceAccountIssuer == \"\" {\n\t\t\t\treturn fmt.Errorf(\"discoveryService URL must be specified\")\n\t\t\t}\n\t\t} else {\n\t\t\tif supportsPublicJWKS(clusterSpec) && clusterSpec.API.PublicName != \"\" {\n\t\t\t\tserviceAccountIssuer = \"https://\" + clusterSpec.API.PublicName\n\t\t\t} else {\n\t\t\t\tserviceAccountIssuer = \"https://api.internal.\" + b.ClusterName\n\t\t\t}\n\t\t}\n\t\tkubeAPIServer.ServiceAccountIssuer = &serviceAccountIssuer\n\t}\n\tkubeAPIServer.ServiceAccountJWKSURI = new(*kubeAPIServer.ServiceAccountIssuer + \"/openid/v1/jwks\")\n\t// We set apiserver ServiceAccountKey and ServiceAccountSigningKeyFile in nodeup\n\n\treturn nil\n}\n\nfunc supportsPublicJWKS(clusterSpec *kops.ClusterSpec) bool {\n\tif !fi.ValueOf(clusterSpec.KubeAPIServer.AnonymousAuth) {","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/model/components/discovery.go#L65-L101","documentation":"When ServiceAccountIssuerDiscovery.DiscoveryService is set, its URL field is used verbatim as the service account issuer/discovery URL. If the URL is empty, kOps cannot construct the issuer and returns this validation error.","triggerScenarios":"Cluster spec defines serviceAccountIssuerDiscovery.discoveryService but leaves discoveryService.url unset (empty string) during BuildOptions.","commonSituations":"Partial YAML: discoveryService key added without url; templating variable that expanded to empty; copy-paste of a sample config missing the url field.","solutions":["Set discoveryService.url to the HTTPS URL serving OIDC discovery (/.well-known/openid-configuration and jwks)","Remove the empty discoveryService block so the default issuer logic is used instead","Validate the cluster spec with kops before applying"],"exampleFix":"// before\nserviceAccountIssuerDiscovery:\n  discoveryService: {}\n// after\nserviceAccountIssuerDiscovery:\n  discoveryService:\n    url: \"https://discovery.example.com\"","handlingStrategy":"validation","validationCode":"if said := spec.ServiceAccountIssuerDiscovery; said != nil && said.DiscoveryService != nil && said.DiscoveryService.URL == \"\" {\n    return fmt.Errorf(\"discoveryService.url is required when discoveryService is set\")\n}","typeGuard":"null","tryCatchPattern":"if err := buildOptions(); err != nil {\n    if strings.Contains(err.Error(), \"discoveryService URL must be specified\") {\n        // populate discoveryService.url in the spec\n    }\n    return err\n}","preventionTips":["Validate required fields in cluster spec before apply","Avoid templating that can render url empty","Use kops editor/toolbox to verify the discovery block"],"tags":["config","validation","oidc","service-account"],"backgroundTag":"missing-required-argument","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}