microsoft/aspire · error · InvalidOperationException
BrowserMessageStrings.BrowserLogsTrackedBrowserProfileConfli…
Error message
BrowserMessageStrings.BrowserLogsTrackedBrowserProfileConflict
What it means
ValidateProfileCompatibility (called from AcquireAsync) throws when a browser host for the same executable + user data root already exists under a tracked profile directory whose name differs from the requested one. One user data root maps to exactly one tracked profile; honoring a conflicting request would corrupt session isolation, so the registry refuses it.
Solutions
- Use one consistent profile configuration per (browser executable, user data root) pair.
- Request a different user data root if you need a different profile directory.
- Release all existing leases and let the tracked host shut down before re-acquiring with a different profile.
Example fix
// before
var first = await registry.AcquireAsync(new BrowserConfiguration { Browser = b, ProfileName = "default" }, ct);
var second = await registry.AcquireAsync(new BrowserConfiguration { Browser = b, ProfileName = "automation" }, ct); // same root, conflict
// after
var second = await registry.AcquireAsync(new BrowserConfiguration { Browser = b, ProfileName = "automation", UserDataRoot = alternateRoot }, ct); Defensive patterns
Strategy: validation
Validate before calling
// Keep a single profile name per user data root across the application private const string TrackedProfileName = "aspire-tracked"; // reuse everywhere instead of ad-hoc names
Try / catch
try { lease = await registry.AcquireAsync(config, ct); }
catch (InvalidOperationException ex) when (ex.Message.Contains("profile", StringComparison.OrdinalIgnoreCase)) { logger.LogError(ex, "Profile conflict on {Root}; use a distinct user data root or the existing profile.", config.UserDataRoot); } Prevention
- Centralize browser profile configuration in one constant/options type.
- Never share a user data directory between differently configured hosts.
- Release all leases before changing profile settings.
When it happens
Trigger: AcquireAsync with a configuration whose resolved user data root already hosts a tracked browser with a different profile directory name — e.g. the first lease used the default profile and a later lease requests a custom profile name for the same root.
Common situations: Mixing lease acquisitions with different profile settings for the same browser; two app hosts or two components sharing one user data directory but configured with different profile names; config drift between runs.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- BrowserMessageStrings.BrowserLogsTrackedBrowserProfileConfli…
- Browser debug connection closed by the remote endpoint with…
- Browser profile ' ' matched multiple Chromium profiles…
- Browser profile ' ' was not found under ' '. Specify the…
- Browser user data directory
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/7d6eb0a012d04262.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Browsers/BrowserHostRegistry.cs:365
return profile;
}
private static void ValidateProfileCompatibility(BrowserHostIdentity identity, string? existingProfileDirectoryName, string? requestedProfileDirectoryName)
{
// A request without an explicit profile can attach to any tracked browser for the same user data root. Once a
// caller asks for a named profile, however, reusing a host launched for a different profile would put the session
// in the wrong browser context, so fail instead of silently attaching to the wrong profile.
// Profile directory names are case-insensitive on Windows and macOS (default APFS) but case-sensitive on Linux.
// We compare with OrdinalIgnoreCase intentionally so a request for "default" attaches to a host that was
// launched with "Default": Chromium itself accepts either casing on Windows/macOS, and on Linux the user is
// expected to specify the literal directory name. We err on the side of attaching rather than rejecting.
if (requestedProfileDirectoryName is null ||
string.Equals(existingProfileDirectoryName, requestedProfileDirectoryName, StringComparison.OrdinalIgnoreCase))
{
return;
}
throw new InvalidOperationException(
string.Format(
CultureInfo.CurrentCulture,
BrowserMessageStrings.BrowserLogsTrackedBrowserProfileConflict,
identity.UserDataRootPath,
existingProfileDirectoryName ?? BrowserMessageStrings.BrowserLogsDefaultProfileName,
requestedProfileDirectoryName));
}
private static string FormatDebugEndpoint(Uri? debugEndpoint) =>
debugEndpoint?.ToString() ?? "private CDP pipe";
private sealed class BrowserHostEntry(IBrowserHost host, string? profileDirectoryName, int ReferenceCount)
{
public IBrowserHost Host { get; } = host;
public string? ProfileDirectoryName { get; } = profileDirectoryName;
public int ReferenceCount { get; set; } = ReferenceCount;View on GitHub (pinned to 25830f84bd)