{"record":{"id":"913cbc4445cdd1c2","repo":"microsoft/aspire","slug":"clusterissuer-issuer-name-has-no-spec-configure-it-with","errorCode":null,"errorMessage":"ClusterIssuer '{issuer.Name}' has no spec. Configure it with WithLetsEncryptProduction(), WithLetsEncryptStaging(), or WithAcmeServer().","messagePattern":"ClusterIssuer '(.+?)' has no spec\\. Configure it with WithLetsEncryptProduction\\(\\), WithLetsEncryptStaging\\(\\), or WithAcmeServer\\(\\)\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Kubernetes/CertManagerExtensions.cs","lineNumber":426,"sourceCode":"            // not found) or fails. Deleting while cert-manager is still alive also lets the\n            // controller clean up the ACME account secret it created in the cert-manager\n            // namespace.\n            step.RequiredBy($\"helm-uninstall-{chartName}\");\n            step.RequiredBy(WellKnownPipelineSteps.Destroy);\n            steps.Add(step);\n        }\n\n        return Task.FromResult<IEnumerable<PipelineStep>>(steps);\n    }\n\n    private static async Task ApplyClusterIssuerAsync(\n        PipelineStepContext context,\n        CertManagerResource certManager,\n        CertManagerIssuerResource issuer)\n    {\n        if (issuer.Spec is null)\n        {\n            throw new InvalidOperationException(\n                $\"ClusterIssuer '{issuer.Name}' has no spec. Configure it with WithLetsEncryptProduction(), \" +\n                \"WithLetsEncryptStaging(), or WithAcmeServer().\");\n        }\n\n        if (issuer.Solvers.Count == 0)\n        {\n            throw new InvalidOperationException(\n                $\"ClusterIssuer '{issuer.Name}' has no solvers configured. Add at least one \" +\n                \"solver via WithHttp01Solver().\");\n        }\n\n        var environment = certManager.Parent;\n\n        var manifest = await BuildClusterIssuerManifestAsync(context.Model, certManager, issuer, context.Logger, context.CancellationToken)\n            .ConfigureAwait(false);\n\n        context.Logger.LogInformation(\n            \"Applying cert-manager ClusterIssuer '{IssuerName}'.\", issuer.Name);","sourceCodeStart":408,"sourceCodeEnd":444,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Kubernetes/CertManagerExtensions.cs#L408-L444","documentation":"During publishing, ApplyClusterIssuerAsync renders the ClusterIssuer manifest. If issuer.Spec is null — no ACME configuration was ever applied — there is nothing to serialize, so the publisher throws InvalidOperationException telling you which configuration methods to call.","triggerScenarios":"Publishing a model where AddClusterIssuer was called but neither WithLetsEncryptProduction(), WithLetsEncryptStaging(), nor WithAcmeServer() was invoked on the resulting issuer.","commonSituations":"Creating a ClusterIssuer placeholder and deferring configuration, or calling AddClusterIssuer without chaining any configuration extension.","solutions":["Chain WithLetsEncryptProduction() on the ClusterIssuer builder for production Let's Encrypt.","Use WithLetsEncryptStaging() while testing to avoid ACME rate limits.","Use WithAcmeServer() for a custom ACME directory endpoint.","Remove the issuer from the model if it is intentionally unconfigured."],"exampleFix":"// before\nvar issuer = certManager.AddClusterIssuer(\"letsencrypt\");\n\n// after\nvar issuer = certManager.AddClusterIssuer(\"letsencrypt\")\n    .WithLetsEncryptProduction(\"admin@example.com\");","handlingStrategy":"validation","validationCode":"if (issuer.Spec is null) issuerBuilder.WithLetsEncryptProduction(email); // configure before publish","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always chain a configuration method (WithLetsEncryptProduction/Staging/WithAcmeServer) onto AddClusterIssuer.","Review issuer configuration in code review before publishing."],"tags":["kubernetes","cert-manager","publish","missing-configuration"],"backgroundTag":"missing-required-config","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T09:17:21.228Z"}