{"record":{"id":"13c75afaa20fe5bb","repo":"microsoft/aspire","slug":"resource-resource-name-is-assigned-to-compute-environment","errorCode":null,"errorMessage":"Resource '{resource.Name}' is assigned to compute environment '{targetName}' but binds Kubernetes persistent volume '{annotation.Volume.Name}' which belongs to environment '{volumeEnvironment.Name}'. A workload can only bind persistent volumes declared on its Kubernetes compute environment. Declare the volume on the workload's Kubernetes environment, or assign the workload to '{supportedTargetName}' with WithComputeEnvironment.","messagePattern":"Resource '(.+?)' is assigned to compute environment '(.+?)' but binds Kubernetes persistent volume '(.+?)' which belongs to environment '(.+?)'\\. A workload can only bind persistent volumes declared on its Kubernetes compute environment\\. Declare the volume on the workload's Kubernetes environment, or assign the workload to '(.+?)' with WithComputeEnvironment\\.","errorType":"exception","errorClass":"DistributedApplicationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Kubernetes/KubernetesEnvironmentExtensions.cs","lineNumber":244,"sourceCode":"            ApplyRunModeContainerVolumeName(resource, annotation);\n        }\n    }\n\n    private static void ValidatePublishModePersistentVolumeBindings(PersistentVolumeBinding[] bindings)\n    {\n        foreach (var (resource, annotation) in bindings)\n        {\n            var targetEnvironment = resource.GetComputeEnvironment();\n            var volumeEnvironment = annotation.Volume.Parent;\n\n            // AKS owns an inner Kubernetes environment, so a binding is valid when the workload\n            // targets either the Kubernetes environment directly or its owning compute environment.\n            if (targetEnvironment != volumeEnvironment &&\n                targetEnvironment != volumeEnvironment.OwningComputeEnvironment)\n            {\n                var targetName = targetEnvironment?.Name ?? \"<none>\";\n                var supportedTargetName = (volumeEnvironment.OwningComputeEnvironment ?? volumeEnvironment).Name;\n                throw new DistributedApplicationException(\n                    $\"Resource '{resource.Name}' is assigned to compute environment '{targetName}' but binds \" +\n                    $\"Kubernetes persistent volume '{annotation.Volume.Name}' which belongs to environment \" +\n                    $\"'{volumeEnvironment.Name}'. A workload can only bind persistent volumes declared on its \" +\n                    $\"Kubernetes compute environment. Declare the volume on the workload's Kubernetes environment, \" +\n                    $\"or assign the workload to '{supportedTargetName}' with WithComputeEnvironment.\");\n            }\n        }\n    }\n\n    private static void ApplyRunModeContainerVolumeName(\n        IResource resource,\n        KubernetesPersistentVolumeBindingAnnotation binding)\n    {\n        if (resource is not ContainerResource || binding.RunModeContainerVolumeName is not { } localVolumeName)\n        {\n            return;\n        }\n","sourceCodeStart":226,"sourceCodeEnd":262,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Kubernetes/KubernetesEnvironmentExtensions.cs#L226-L262","documentation":"In publish mode, a workload assigned to a compute environment binds a Kubernetes persistent volume declared on a different Kubernetes environment. Workloads may only bind volumes declared on their own Kubernetes environment (or the environment that owns their compute environment), so validation throws DistributedApplicationException.","triggerScenarios":"Calling WithComputeEnvironment to assign a resource to environment A while binding a persistent volume created via environment B, then publishing.","commonSituations":"Multi-cluster/multi-environment AppHosts where volumes and workloads are declared on different Kubernetes environments; copy-pasted volume wiring after adding a second cluster.","solutions":["Declare the persistent volume on the workload's own Kubernetes environment.","Reassign the workload with WithComputeEnvironment to the environment (or its owning compute environment) that declares the volume.","Move the volume declaration into the target environment used by the workload."],"exampleFix":"// before\nvar volume = clusterA.AddPersistentVolume(\"data\", ...);\nvar svc = builder.AddProject<Projects.Api>(\"api\").WithComputeEnvironment(clusterB).WithVolume(volume);\n// after\nvar volume = clusterB.AddPersistentVolume(\"data\", ...);\nvar svc = builder.AddProject<Projects.Api>(\"api\").WithComputeEnvironment(clusterB).WithVolume(volume);","handlingStrategy":"validation","validationCode":"if (volume.Parent != workloadEnvironment && volume.Parent.OwningComputeEnvironment != workloadEnvironment) throw new Exception(\"Volume belongs to a different Kubernetes environment.\");","typeGuard":null,"tryCatchPattern":"try { PublishAsync(); } catch (DistributedApplicationException ex) when (ex.Message.Contains(\"belongs to environment\")) { /* re-declare volume on the correct environment */ }","preventionTips":["Declare volumes on the same environment as the workloads that bind them","Check WithComputeEnvironment assignments when adding volumes","Keep one Kubernetes environment per workload group where possible"],"tags":["kubernetes","volumes","publish","environment-mismatch"],"backgroundTag":"invalid-state-transition","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"}