{"record":{"id":"461f3f935c25f723","repo":"microsoft/aspire","slug":"toolbox-name-changed-concurrently-target-version-version-is","errorCode":null,"errorMessage":"Toolbox '{name}' changed concurrently: target version '{version}' is no longer visible. No further changes were made.","messagePattern":"Toolbox '(.+?)' changed concurrently: target version '(.+?)' is no longer visible\\. No further changes were made\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxReconciler.cs","lineNumber":492,"sourceCode":"            throw CreateConcurrentChangeException(\n                name,\n                $\"default version '{state.DefaultVersion}' is not managed by Aspire\");\n        }\n\n        throw new InvalidOperationException(\n            $\"Toolbox '{name}' already exists but is not managed by Aspire. No changes were made.\");\n    }\n\n    private static void ValidatePromotionTarget(\n        FoundryToolboxDeploymentDefinition definition,\n        FoundryToolboxState state,\n        string version)\n    {\n        var target = state.Versions.FirstOrDefault(candidate =>\n            string.Equals(candidate.Version, version, StringComparison.Ordinal));\n        if (target is null)\n        {\n            throw CreateConcurrentChangeException(\n                definition.Name,\n                $\"target version '{version}' is no longer visible\");\n        }\n\n        if (!IsAspireManaged(target) ||\n            !target.Metadata.TryGetValue(\n                FoundryToolboxDeploymentDefinition.ConfigurationHashMetadataKey,\n                out var configurationHash) ||\n            !string.Equals(configurationHash, definition.ConfigurationHash, StringComparison.Ordinal))\n        {\n            throw CreateConcurrentChangeException(\n                definition.Name,\n                $\"target version '{version}' no longer has the expected Aspire ownership and configuration\");\n        }\n    }\n\n    private static bool IsAspireManaged(FoundryToolboxVersionState version) =>\n        version.Metadata.TryGetValue(","sourceCodeStart":474,"sourceCodeEnd":510,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxReconciler.cs#L474-L510","documentation":"ValidatePromotionTarget confirms, before validating ownership, that the version Aspire just promoted still exists in the Toolbox's version list when the post-promotion state is read. If the target version was deleted concurrently, the reconciler throws this error and makes no further changes. It prevents Aspire from validating or reporting success for a version that no longer exists.","triggerScenarios":"PromoteOwnedVersionAsync calls ValidatePromotionTarget with the promoted version string, and state.Versions contains no entry whose Version matches — i.e., the version was deleted by another actor between promotion and the post-promotion GetAsync read.","commonSituations":"A retention/cleanup policy or pipeline deletes old Toolbox versions while a deploy promotes one; another developer removes the version in the portal mid-deploy; a racing Aspire reconcile deletes the version it previously published.","solutions":["Re-run the deploy so Aspire re-publishes the version and completes the promotion","Check whether a cleanup/retention job deletes Toolbox versions during deploys and reschedule or exclude Aspire-managed versions","Coordinate with team members to avoid deleting versions while a deployment is running","Serialize reconciles per environment with a pipeline concurrency group"],"exampleFix":"// before: cleanup job deletes versions older than 1 day, deploy promotes 1.3.0 published moments ago\n\n// after: exclude the version being deployed from cleanup\n// cleanup filter: delete versions NOT matching current AppHost-declared version\n#pragma warning disable ASPIREFOUNDRY001\ncbuilder.AddFoundryToolbox(\"my-toolbox\", version: \"1.3.0\");","handlingStrategy":"retry","validationCode":"// Confirm the target version exists before deploying\nvar state = await administration.GetAsync(definition.Name, ct);\nbool versionVisible = state?.Versions.Any(v => v.Version == definition.Version) == true;\nif (state is not null && !versionVisible) { /* version was deleted; let reconcile republish */ }","typeGuard":"bool VersionExists(FoundryToolboxState? state, string version) =>\n    state?.Versions.Any(v => string.Equals(v.Version, version, StringComparison.Ordinal)) == true;","tryCatchPattern":"try\n{\n    await reconciler.ReconcileAsync(definition, ct);\n}\ncatch (ConcurrentChangeException)\n{\n    // Target version was deleted mid-flight; safe to re-run so it is republished.\n    await reconciler.ReconcileAsync(definition, ct);\n}","preventionTips":["Exclude Aspire-managed/current versions from cleanup or retention jobs","Freeze version deletions during deployment windows","Use a single owner (Aspire) for Toolbox version lifecycle"],"tags":["concurrency","azure","versioning","reconciliation"],"backgroundTag":"concurrent-change-detected","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"}