{"record":{"id":"949b8484699e960c","repo":"microsoft/aspire","slug":"browsermessagestrings-browserendpointdiscovery","errorCode":null,"errorMessage":"BrowserMessageStrings.BrowserLogsTrackedBrowserProfileConflict","messagePattern":"BrowserMessageStrings\\.BrowserLogsTrackedBrowserProfileConflict","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Browsers/BrowserEndpointDiscovery.cs","lineNumber":139,"sourceCode":"        }\n        catch (Exception ex) when (!cancellationToken.IsCancellationRequested && ex is HttpRequestException or IOException or JsonException or OperationCanceledException)\n        {\n            _logger.LogDebug(ex, \"Tracked browser endpoint metadata '{MetadataPath}' points to endpoint '{Endpoint}', but probing /json/version failed.\", metadataPath, endpoint);\n            endpointResponded = false;\n        }\n\n        if (!endpointResponded)\n        {\n            _logger.LogDebug(\"Tracked browser endpoint metadata '{MetadataPath}' points to endpoint '{Endpoint}', but it did not respond to /json/version.\", metadataPath, endpoint);\n            TryDelete(metadataPath);\n            return null;\n        }\n\n        // At this point the sidecar points at a live Aspire-launched browser for the same user-data root. A profile\n        // mismatch is therefore a real conflict, not stale metadata, and should be reported to the caller.\n        if (!string.Equals(metadata.ProfileDirectoryName, profileDirectoryName, StringComparison.OrdinalIgnoreCase))\n        {\n            throw new InvalidOperationException(\n                string.Format(\n                    CultureInfo.CurrentCulture,\n                    BrowserMessageStrings.BrowserLogsTrackedBrowserProfileConflict,\n                    identity.UserDataRootPath,\n                    metadata.ProfileDirectoryName ?? BrowserMessageStrings.BrowserLogsDefaultProfileName,\n                    profileDirectoryName ?? BrowserMessageStrings.BrowserLogsDefaultProfileName));\n        }\n\n        return metadata with { Endpoint = endpoint.ToString() };\n    }\n\n    public static async Task WriteAsync(BrowserHostIdentity identity, string? profileDirectoryName, Uri endpoint, int processId, CancellationToken cancellationToken)\n    {\n        var metadataPath = GetEndpointMetadataFilePath(identity.UserDataRootPath);\n        var tempPath = $\"{metadataPath}.{Guid.NewGuid():N}.tmp\";\n        // The sidecar captures the identity that was used to launch the owned browser, not just the endpoint URL. That\n        // lets a future AppHost reject metadata from a different browser executable or user-data root before connecting.\n        //","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Browsers/BrowserEndpointDiscovery.cs#L121-L157","documentation":"BrowserEndpointDiscovery.TryReadAndValidateAsync reads sidecar metadata tracking a live Aspire-launched browser for a given user-data root. If the tracked browser exists for the same user-data root but its profile directory name differs from the requested profile, this is treated as a genuine conflict (not stale metadata) and throws with BrowserLogsTrackedBrowserProfileConflict, reporting the user-data root, the tracked profile name, and the requested profile name.","triggerScenarios":"Requesting browser-logs capture with profile P while an already-running Aspire-launched browser for the same user-data root was started with profile Q; calling TryReadAndValidateAsync again after switching the profile configuration without restarting the tracked browser.","commonSituations":"Changing the profile name in WithBrowserLogs between app-host runs while an old browser instance is still open; two app-host sessions sharing a user-data root but configured with different profiles; a leftover browser process from a crashed session holding the user-data root.","solutions":["Close the currently running tracked browser (or kill its process) so discovery can launch a fresh one with the requested profile.","Make the profile name in your WithBrowserLogs configuration match the profile of the running browser.","Clear stale sidecar metadata after killing the browser and retry.","Avoid sharing one user-data root across app hosts configured with different profiles."],"exampleFix":"// before\n.WithBrowserLogs(new Dictionary<string, string?> { [\"profile\"] = \"newprofile\" }) // old browser running with 'oldprofile'\n\n// after: stop the old browser first, or keep profile consistent\n# taskkill /IM chrome.exe /F  (or close the tracked browser window)\n.WithBrowserLogs(new Dictionary<string, string?> { [\"profile\"] = \"oldprofile\" })","handlingStrategy":"retry","validationCode":"// Before requesting browser logs, ensure no tracked browser with a different profile is running for the same user-data root\n// (close prior browser instances or match the configured profile to the running one).","typeGuard":null,"tryCatchPattern":"try { await discovery.TryReadAndValidateAsync(...); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"profile conflict\"))\n{ logger.LogWarning(ex, \"Killing tracked browser with mismatched profile and retrying\"); /* kill browser, clear metadata, retry once */ }","preventionTips":["Keep the profile name stable across runs for a given user-data root.","Close leftover tracked browsers before changing the profile.","Avoid sharing one user-data root between app hosts with different profiles."],"tags":["browser","profile-conflict","browser-logs","state-conflict"],"backgroundTag":"conflicting-config-options","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"}