microsoft/aspire · error · InvalidOperationException
Developer Control Plane (DCP) kubeconfig did not contain a…
Error message
Developer Control Plane (DCP) kubeconfig did not contain a valid server URI.
What it means
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.
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.
Example fix
// consumer-side retry around doctor's DCP check
try
{
var kubeconfig = await DcpKubeconfig.ReadFileWithRetryAsync(path, ct);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("server URI"))
{
File.Delete(path); // discard partial kubeconfig
Console.Error.WriteLine("DCP wrote an invalid kubeconfig; restarting DCP check...");
} Defensive patterns
Strategy: retry
Validate before calling
var text = File.ReadAllText(kubeconfigPath);
var serverLine = text.Split('\n').FirstOrDefault(l => l.TrimStart().StartsWith("server:"));
var serverValue = serverLine?.Split(':', 2)[1].Trim().Trim('"');
bool valid = !string.IsNullOrWhiteSpace(serverValue) && Uri.TryCreate(serverValue, UriKind.Absolute, out _); Type guard
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); } Try / catch
try { var kc = await DcpKubeconfig.ReadFileWithRetryAsync(path, ct); }
catch (InvalidOperationException ex) when (ex.Message.Contains("server URI")) { File.Delete(path); await RestartDcpAndRetryAsync(); } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- Developer Control Plane (DCP) exited before writing…
- Error parsing URIs from configuration value
- Failed to start Developer Control Plane (DCP).
- Invalid value " " for "--dcp-dependency-check-timeout"…
- No fully trusted exportable developer certificate with a…
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/fa2c21ce8f15414a.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Cli/Utils/EnvironmentChecker/DcpKubeconfig.cs:75
// users:
// - name: dcp
// user:
// client-certificate-data: <base64 PEM>
// client-key-data: <base64 PEM>
// The doctor probe only needs connection material, so parse the scalar fields directly
// instead of adding a YAML dependency to the NativeAOT CLI.
foreach (var line in content.Split('\n'))
{
server ??= TryReadScalar(line, "server");
token ??= TryReadScalar(line, "token");
certificateAuthorityData ??= TryReadScalar(line, "certificate-authority-data");
clientCertificateData ??= TryReadScalar(line, "client-certificate-data");
clientKeyData ??= TryReadScalar(line, "client-key-data");
}
if (string.IsNullOrWhiteSpace(server) || !Uri.TryCreate(server, UriKind.Absolute, out var serverUri))
{
throw new InvalidOperationException(DoctorCommandStrings.DcpKubeconfigMissingServerDetails);
}
return new DcpKubeconfig
{
Server = serverUri,
Token = token,
CertificateAuthorityCertificates = certificateAuthorityData is null
? []
: LoadCertificates(certificateAuthorityData),
ClientCertificate = clientCertificateData is not null && clientKeyData is not null
? LoadClientCertificate(clientCertificateData, clientKeyData)
: null
};
}
public void Dispose()
{
foreach (var certificate in CertificateAuthorityCertificates)View on GitHub (pinned to 25830f84bd)