{"record":{"id":"a08a1b706ef275be","repo":"argoproj/argo-workflows","slug":"clientid-empty","errorCode":null,"errorMessage":"clientID empty","messagePattern":"clientID empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/auth/sso/sso.go","lineNumber":129,"sourceCode":"\nfunc New(ctx context.Context, c Config, secretsIf corev1.SecretInterface, baseHRef string, secure bool) (Interface, error) {\n\treturn newSso(ctx, providerFactoryOIDC, c, secretsIf, baseHRef, secure)\n}\n\nfunc newSso(\n\tctx context.Context,\n\tfactory providerFactory,\n\tc Config,\n\tsecretsIf corev1.SecretInterface,\n\tbaseHRef string,\n\tsecure bool,\n) (Interface, error) {\n\tbaseHRef = authcookie.NormalizePath(baseHRef)\n\tif c.Issuer == \"\" {\n\t\treturn nil, fmt.Errorf(\"issuer empty\")\n\t}\n\tif c.ClientID.Name == \"\" || c.ClientID.Key == \"\" {\n\t\treturn nil, fmt.Errorf(\"clientID empty\")\n\t}\n\tif c.ClientSecret.Name == \"\" || c.ClientSecret.Key == \"\" {\n\t\treturn nil, fmt.Errorf(\"clientSecret empty\")\n\t}\n\tclientSecretObj, err := secretsIf.Get(ctx, c.ClientSecret.Name, metav1.GetOptions{})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Create http client\n\thttpClientConfig := HTTPClientConfig{\n\t\tInsecureSkipVerify: c.InsecureSkipVerify,\n\t\tRootCA:             c.RootCA,\n\t}\n\thttpClient, err := createHTTPClient(httpClientConfig)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create HTTP client: %w\", err)\n\t}","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/server/auth/sso/sso.go#L111-L147","documentation":"newSso requires both the Kubernetes Secret name and the key inside it for the OIDC client ID (sso.clientID.name and sso.clientID.key). If either is empty the constructor returns 'clientID empty'. The client ID identifies the argo-server application to the OIDC provider and is stored in a Secret rather than the ConfigMap for consistency with clientSecret handling.","triggerScenarios":"argo-server SSO ConfigMap sets sso.issuer and sso.clientSecret but the `sso.clientID.name` / `sso.clientID.key` keys are absent or blank, so newSso's validation fails during argo-server startup (or when tests build Config with an empty ClientID).","commonSituations":"Older SSO configurations that specified the client ID only in the ConfigMap (pre-3.x style) not migrated to the Secret-based format; typo in the ConfigMap keys; partial ConfigMap template where the clientID section was deleted.","solutions":["Create/extend the SSO Secret (default name `argo-server-sso-secret`) with a key holding the client ID, e.g. `kubectl create secret generic argo-server-sso-secret --from-literal=client-id=YOUR_CLIENT_ID`","Set `sso.clientID.name: argo-server-sso-secret` and `sso.clientID.key: client-id` in the argo-server SSO ConfigMap and restart argo-server","Ensure the Secret exists in the argo namespace and is readable by the argo-server service account"],"exampleFix":"# ConfigMap\n# before\nsso.clientSecret:\n  name: argo-server-sso-secret\n  key: client-secret\n# after\nsso.clientID:\n  name: argo-server-sso-secret\n  key: client-id\nsso.clientSecret:\n  name: argo-server-sso-secret\n  key: client-secret","handlingStrategy":"validation","validationCode":"sec, err := clientset.CoreV1().Secrets(ns).Get(ctx, \"argo-server-sso-secret\", metav1.GetOptions{})\nif err != nil { return err }\nif _, ok := sec.Data[\"client-id\"]; !ok {\n    return errors.New(\"Secret argo-server-sso-secret lacks key client-id\")\n}\n// and ensure ConfigMap has sso.clientID.name/key set","typeGuard":"func clientIDConfigured(cfg sso.Config) bool {\n    return cfg.ClientID.Name != \"\" && cfg.ClientID.Key != \"\"\n}","tryCatchPattern":"svc, err := sso.New(ctx, controller, mode, cm, secretsIf, baseHRef, secure)\nif err != nil && strings.Contains(err.Error(), \"clientID empty\") {\n    return fmt.Errorf(\"set sso.clientID.name/key in the SSO ConfigMap and provide the Secret: %w\", err)\n}","preventionTips":["Create the client-ID Secret with kubectl --from-literal=client-id=... before enabling SSO","Keep clientID and clientSecret in the same Secret with matching name in the ConfigMap","After upgrading from legacy ConfigMap-based client ID, migrate to the Secret-based keys","Diff applied ConfigMap against the upstream quick-start template to catch missing sso.clientID keys"],"tags":["sso","oidc","configuration","kubernetes-secret"],"backgroundTag":"sso-clientid-missing","analyzedSha":"35bff19146f5a6ada77468c431f2624bd577e373","analyzedAt":"2026-09-03T19:34:35.908Z","contentChangedAt":"2026-09-03T19:34:35.908Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}