{"record":{"id":"b5309f99fa11d6f7","repo":"microsoft/aspire","slug":"partition-key-paths-cannot-contain-null-or-empty-strings-b5309f","errorCode":null,"errorMessage":"Partition key paths cannot contain null or empty strings.","messagePattern":"Partition key paths cannot contain null or empty strings\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Azure.CosmosDB/AzureCosmosDBExtensions.cs","lineNumber":448,"sourceCode":"    /// <param name=\"name\">Name of container resource.</param>\n    /// <param name=\"partitionKeyPaths\">Hierarchical partition key paths for the container.</param>\n    /// <param name=\"containerName\">The name of the container. If not provided, this defaults to the same value as <paramref name=\"name\"/>.</param>\n    /// <returns>A reference to the <see cref=\"IResourceBuilder{T}\"/>.</returns>\n    [AspireExportIgnore(Reason = \"Polyglot AppHosts use the internal addContainer dispatcher export.\")]\n    public static IResourceBuilder<AzureCosmosDBContainerResource> AddContainer(this IResourceBuilder<AzureCosmosDBDatabaseResource> builder, [ResourceName] string name, IEnumerable<string> partitionKeyPaths, string? containerName = null)\n    {\n        ArgumentNullException.ThrowIfNull(builder);\n        ArgumentException.ThrowIfNullOrEmpty(name);\n        ArgumentNullException.ThrowIfNull(partitionKeyPaths);\n        var partitionKeyPathsArray = partitionKeyPaths.ToArray();\n        if (partitionKeyPathsArray.Length == 0)\n        {\n            throw new ArgumentException(\"At least one partition key path should be provided.\", nameof(partitionKeyPaths));\n        }\n\n        if (partitionKeyPathsArray.Any(string.IsNullOrEmpty))\n        {\n            throw new ArgumentException(\"Partition key paths cannot contain null or empty strings.\", nameof(partitionKeyPaths));\n        }\n\n        // Use the resource name as the container name if it's not provided\n        containerName ??= name;\n\n        var container = new AzureCosmosDBContainerResource(name, containerName, partitionKeyPaths, builder.Resource);\n\n        builder.Resource.Containers.Add(container);\n\n        return builder.ApplicationBuilder.AddResource(container)\n            .WithIconName(\"Box\");\n    }\n\n    /// <summary>\n    /// Configures the Azure Cosmos DB resource to be deployed use the default SKU provided by Azure.\n    /// </summary>\n    /// <param name=\"builder\">The builder for the Azure Cosmos DB resource.</param>\n    /// <returns>A reference to the <see cref=\"IResourceBuilder{T}\"/>.</returns>","sourceCodeStart":430,"sourceCodeEnd":466,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Azure.CosmosDB/AzureCosmosDBExtensions.cs#L430-L466","documentation":"AddContainer validates that every partition key path in the collection is a non-empty, non-null string before creating the Azure Cosmos DB container resource. Cosmos DB requires valid JSON property paths (e.g. '/customerId') as partition keys, so null/empty entries would produce an invalid container definition that would fail later at provisioning time.","triggerScenarios":"Calling AddContainer with a partitionKeyPaths array that includes null elements or empty strings, e.g. new[] { \"/id\", \"\" } or an array built by splitting an empty string.","commonSituations":"Reading partition key paths from configuration where values are missing; string.Split(',') on an empty config value yielding [\"\"]; dynamically building paths in a loop with uninitialized entries.","solutions":["Inspect the partitionKeyPaths array for null/empty entries and remove or correct them","Ensure each path starts with '/' and names a real JSON property in your documents","If paths come from configuration, validate them before calling AddContainer or use a guard that filters entries"],"exampleFix":"// before\nbuilder.AddDatabase(\"cosmos\").AddContainer(\"orders\", \"/customerId,\".Split(','));\n// after\nvar paths = \"/customerId\".Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);\nbuilder.AddDatabase(\"cosmos\").AddContainer(\"orders\", paths);","handlingStrategy":"validation","validationCode":"var paths = (partitionKeyPaths ?? throw new ArgumentNullException(nameof(partitionKeyPaths))).ToArray();\nif (paths.Length == 0 || paths.Any(string.IsNullOrEmpty))\n    throw new ArgumentException(\"All partition key paths must be non-empty.\");","typeGuard":"static bool AreValidPartitionKeyPaths(string[]? paths) =>\n    paths is { Length: > 0 } && paths.All(p => !string.IsNullOrEmpty(p) && p.StartsWith('/'));","tryCatchPattern":"try { builder.AddContainer(\"orders\", name, paths); }\ncatch (ArgumentException ex) when (ex.ParamName == nameof(partitionKeyPaths)) { /* fix config and retry once */ }","preventionTips":["Filter arrays with StringSplitOptions.RemoveEmptyEntries when deriving paths from strings","Validate config-sourced paths at startup","Keep partition key paths in one constant location"],"tags":["cosmosdb","argument-validation","partition-key"],"backgroundTag":"empty-required-field","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T09:17:21.228Z"}