microsoft/aspire · error · InvalidOperationException

Resource ' ' maps both and to Helm values path ' . . '…

Error message

Resource '{resource.Name}' maps both {origins[valuesKey]} and {origin} to Helm values path '{helmKey}.{resourceKey}.{valuesKey}'. Rename one of them so each value has a unique Helm path.

What it means

Thrown by MergeHelmValueMappings in KubernetesPublishingContext when two different origins (e.g. two different environment variable sources or endpoints) both resolve to the same Helm values path '{helmKey}.{resourceKey}.{valuesKey}'. The Kubernetes publisher requires a one-to-one mapping between source values and Helm values paths so generated manifests are unambiguous. It refuses to silently overwrite one value with another.

Solutions

  1. Rename one of the conflicting sources (parameter name or values key) so each has a unique Helm values path
  2. Use the Helm values-key customization API to set an explicit distinct ValuesKey for one of the conflicting mappings
  3. Remove the duplicate source if one of the two values is redundant
  4. Inspect the published Helm values section for the resource to identify which two origins collide

Example fix

// before
var para = builder.AddParameter("db-connection");
var para2 = builder.AddParameter("db_connection"); // both normalize to 'db-connection'
// after
var para = builder.AddParameter("db-connection");
var para2 = builder.AddParameter("db-connection-string"); // unique Helm values path
Defensive patterns

Strategy: validation

Validate before calling

var names = myParameters.Select(p => p.Name.ToHelmValuesSectionName()).ToList();
if (names.Count != names.Distinct().Count()) throw new InvalidOperationException("Duplicate Helm values keys detected");

Try / catch

try { await publishingContext.WriteAsync(outputPath); }
catch (InvalidOperationException ex) when (ex.Message.Contains("maps both")) { logger.LogError(ex, "Helm values path collision: {Msg}", ex.Message); throw; }

Prevention

When it happens

Trigger: Running the Kubernetes publisher (parameterItems/configItems/secretItems) on a resource where two config/environment sources map to the same valuesKey, e.g. two parameters that normalize to the same Helm section name, or an env var and a parameter both colliding on '{helmKey}.{resourceKey}.{valuesKey}'.

Common situations: Defining two AddParameter calls whose names normalize to the same Helm values key; assigning the same environment variable name via different APIs (WithEnvironment and a parameter binding); renaming a parameter so it now collides with an existing one after a version upgrade.

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/842a9b5ef70b60ae. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting.Kubernetes/KubernetesPublishingContext.cs:245

                if (!result.TryGetValue(valuesKey, out var existing))
                {
                    result.Add(valuesKey, value);
                    origins.Add(valuesKey, origin);
                    continue;
                }

                if (value.ParameterSource is not null &&
                    ReferenceEquals(existing.ParameterSource, value.ParameterSource))
                {
                    if (value.IsEmbeddedParameter && !existing.IsEmbeddedParameter)
                    {
                        result[valuesKey] = value;
                    }

                    continue;
                }

                throw new InvalidOperationException(
                    $"Resource '{resource.Name}' maps both {origins[valuesKey]} and {origin} " +
                    $"to Helm values path '{helmKey}.{resourceKey}.{valuesKey}'. Rename one of them " +
                    "so each value has a unique Helm path.");
            }
        }

        return result;
    }

    private async Task AddValuesToHelmSectionAsync(
        IResource resource,
        Dictionary<string, KubernetesResource.HelmValue> contextItems,
        string helmKey)
    {
        if (contextItems.Count <= 0 || _helmValues[helmKey] is not Dictionary<string, object> helmSection)
        {
            return;
        }

View on GitHub (pinned to 25830f84bd)