{"record":{"id":"fa2c21ce8f15414a","repo":"microsoft/aspire","slug":"developer-control-plane-dcp-kubeconfig-did-not-contain-a","errorCode":null,"errorMessage":"Developer Control Plane (DCP) kubeconfig did not contain a valid server URI.","messagePattern":"Developer Control Plane \\(DCP\\) kubeconfig did not contain a valid server URI\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Cli/Utils/EnvironmentChecker/DcpKubeconfig.cs","lineNumber":75,"sourceCode":"        //   users:\n        //   - name: dcp\n        //     user:\n        //       client-certificate-data: <base64 PEM>\n        //       client-key-data: <base64 PEM>\n        // The doctor probe only needs connection material, so parse the scalar fields directly\n        // instead of adding a YAML dependency to the NativeAOT CLI.\n        foreach (var line in content.Split('\\n'))\n        {\n            server ??= TryReadScalar(line, \"server\");\n            token ??= TryReadScalar(line, \"token\");\n            certificateAuthorityData ??= TryReadScalar(line, \"certificate-authority-data\");\n            clientCertificateData ??= TryReadScalar(line, \"client-certificate-data\");\n            clientKeyData ??= TryReadScalar(line, \"client-key-data\");\n        }\n\n        if (string.IsNullOrWhiteSpace(server) || !Uri.TryCreate(server, UriKind.Absolute, out var serverUri))\n        {\n            throw new InvalidOperationException(DoctorCommandStrings.DcpKubeconfigMissingServerDetails);\n        }\n\n        return new DcpKubeconfig\n        {\n            Server = serverUri,\n            Token = token,\n            CertificateAuthorityCertificates = certificateAuthorityData is null\n                ? []\n                : LoadCertificates(certificateAuthorityData),\n            ClientCertificate = clientCertificateData is not null && clientKeyData is not null\n                ? LoadClientCertificate(clientCertificateData, clientKeyData)\n                : null\n        };\n    }\n\n    public void Dispose()\n    {\n        foreach (var certificate in CertificateAuthorityCertificates)","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Cli/Utils/EnvironmentChecker/DcpKubeconfig.cs#L57-L93","documentation":"DcpKubeconfig.Parse reads the kubeconfig file DCP writes and extracts the cluster server URL, token, and client credentials. If the parsed `server` field is missing/blank or not an absolute URI, Parse throws InvalidOperationException indicating the kubeconfig contains no valid server URI - meaning the file is structurally present but the connection endpoint could not be determined.","triggerScenarios":"ReadFileWithRetryAsync successfully reads the DCP-written kubeconfig but the parsed server line is absent, empty, or malformed (e.g. DCP wrote a partial/empty kubeconfig, or the server value is not a valid absolute URL) causing Uri.TryCreate to fail.","commonSituations":"DCP writing a truncated kubeconfig during startup (file observed before fully flushed), a race where the checker read the file mid-write, corrupted previous kubeconfig content, or DCP misconfiguration emitting an empty server address.","solutions":["Retry the operation - the checker already retries reads; a fresh DCP start usually writes a complete kubeconfig.","Delete the stale kubeconfig file/session directory and rerun `aspire doctor` so DCP regenerates it.","Open the kubeconfig file and inspect the `server:` line; if empty/malformed, this indicates a DCP startup problem - check DCP output for errors.","Reinstall/update DCP if it consistently writes invalid kubeconfigs."],"exampleFix":"// consumer-side retry around doctor's DCP check\ntry\n{\n    var kubeconfig = await DcpKubeconfig.ReadFileWithRetryAsync(path, ct);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"server URI\"))\n{\n    File.Delete(path); // discard partial kubeconfig\n    Console.Error.WriteLine(\"DCP wrote an invalid kubeconfig; restarting DCP check...\");\n}","handlingStrategy":"retry","validationCode":"var text = File.ReadAllText(kubeconfigPath);\nvar serverLine = text.Split('\\n').FirstOrDefault(l => l.TrimStart().StartsWith(\"server:\"));\nvar serverValue = serverLine?.Split(':', 2)[1].Trim().Trim('\"');\nbool valid = !string.IsNullOrWhiteSpace(serverValue) && Uri.TryCreate(serverValue, UriKind.Absolute, out _);","typeGuard":"static bool TryGetServerUri(string kubeconfigText, out Uri? uri) { var line = kubeconfigText.Split('\\n').FirstOrDefault(l => l.TrimStart().StartsWith(\"server:\")); var v = line?.Split(':', 2)[1].Trim().Trim('\"'); return v is not null && Uri.TryCreate(v, UriKind.Absolute, out uri); }","tryCatchPattern":"try { var kc = await DcpKubeconfig.ReadFileWithRetryAsync(path, ct); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"server URI\")) { File.Delete(path); await RestartDcpAndRetryAsync(); }","preventionTips":["Allow DCP time to finish writing kubeconfig before reading; rely on the built-in retry loop.","Delete stale/partial kubeconfig files before starting a new DCP session.","If it recurs, capture DCP output - it usually indicates a DCP startup failure, not a reader bug."],"tags":["dcp","kubeconfig","uri","parsing","doctor"],"backgroundTag":"invalid-url-format","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}