microsoft/aspire · error · DistributedApplicationException

Kubernetes persistent volume

Error message

Kubernetes persistent volume '{volume.Name}' is used by both local container and host-process resources ({resourceNames}). Run mode cannot provide one shared backing store across those execution types. Use only containers or only projects/executables for this volume.

What it means

A Kubernetes persistent volume is bound simultaneously by local container resources and by host-process resources (projects/executables running on the host). Run mode cannot provide a single shared backing store across those two execution types, so validation throws DistributedApplicationException.

Solutions

  1. Use the volume exclusively with container resources, or exclusively with projects/executables.
  2. Split the storage into two separate volumes: one for containers, one for host-process resources.
  3. Switch the host-process consumer to a container so all consumers share the same execution type.

Example fix

// before
volume.Bind(vol, postgres);   // container
volume.Bind(vol, migration);  // executable -> conflict
// after
volume.Bind(vol, postgres);
migrationVolume.Bind(migrationVolume, migration);
Defensive patterns

Strategy: validation

Validate before calling

bool allContainers = bindings.All(b => b.Resource is ContainerResource) || bindings.All(b => b.Resource is ProjectResource or ExecutableResource);

Try / catch

try { RunAppHostAsync(); } catch (DistributedApplicationException ex) when (ex.Message.Contains("both local container and host-process")) { /* split volumes by execution type */ }

Prevention

When it happens

Trigger: The same named persistent volume is referenced both by a container resource and by a project/executable resource, then the AppHost is run.

Common situations: Sharing a data directory between a database container (e.g. Postgres) and a worker console project that processes the same files locally; mixed container/host-process topologies evolving over time.

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


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/295f6f645826a0b0. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting.Kubernetes/KubernetesEnvironmentExtensions.cs:189

            {
                var containers = volumeGroup.Where(item => item.Resource is ContainerResource).ToArray();

                // Only host processes that asked for the environment path materialize an IAspireStore
                // directory. A project or executable bound to a publish-only volume consumes no local
                // backing store in run mode, so it cannot conflict with a container's named volume.
                // Rejecting it would break AppHosts that predate the environment-path feature.
                //
                // Resolving the env name covers both spellings, and is order-independent because it
                // runs here rather than when either builder method was called.
                var hostProcesses = volumeGroup.Where(item =>
                    item.Resource is ProjectResource or ExecutableResource &&
                    GetLocalPathEnvironmentVariableName(item.Resource, item.Annotation) is not null).ToArray();

                if (containers.Length > 0 && hostProcesses.Length > 0)
                {
                    var volume = volumeGroup.First().Annotation.Volume;
                    var resourceNames = string.Join(", ", containers.Concat(hostProcesses).Select(item => $"'{item.Resource.Name}'"));
                    throw new DistributedApplicationException(
                        $"Kubernetes persistent volume '{volume.Name}' is used by both local container and host-process resources ({resourceNames}). " +
                        $"Run mode cannot provide one shared backing store across those execution types. Use only containers or only projects/executables for this volume.");
                }
            }
        }
    }

    private static string? GetLocalPathEnvironmentVariableName(
        IResource resource,
        KubernetesPersistentVolumeBindingAnnotation annotation)
    {
        // WithPersistentVolume(volume, mountPath, env) records the env on the binding itself.
        if (annotation.EnvironmentVariableName is not null)
        {
            return annotation.EnvironmentVariableName;
        }

        // The name-match composition spells it on a separate mount instead:

View on GitHub (pinned to 25830f84bd)