{"record":{"id":"cac288552276f1bb","repo":"microsoft/aspire","slug":"partition-key-paths-must-be-a-string-or-a-string-collection","errorCode":null,"errorMessage":"Partition key paths must be a string or a string collection.","messagePattern":"Partition key paths must be a string or a string collection\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Azure.CosmosDB/AzureCosmosDBExtensions.cs","lineNumber":422,"sourceCode":"    /// <summary>\n    /// Adds an Azure Cosmos DB container resource\n    /// </summary>\n    [AspireExport(\"addContainer\")]\n    internal static IResourceBuilder<AzureCosmosDBContainerResource> AddContainerForPolyglot(\n        this IResourceBuilder<AzureCosmosDBDatabaseResource> builder,\n        [ResourceName] string name,\n        [AspireUnion(typeof(string), typeof(IEnumerable<string>))] object partitionKeyPaths,\n        string? containerName = null)\n    {\n        ArgumentNullException.ThrowIfNull(builder);\n        ArgumentException.ThrowIfNullOrEmpty(name);\n        ArgumentNullException.ThrowIfNull(partitionKeyPaths);\n\n        return partitionKeyPaths switch\n        {\n            string partitionKeyPath => builder.AddContainer(name, partitionKeyPath, containerName),\n            IEnumerable<string> partitionKeyPathCollection => builder.AddContainer(name, partitionKeyPathCollection, containerName),\n            _ => throw new ArgumentException(\"Partition key paths must be a string or a string collection.\", nameof(partitionKeyPaths))\n        };\n    }\n\n    /// <summary>\n    /// Adds a container to the associated Cosmos DB database resource with hierarchical partition keys.\n    /// </summary>\n    /// <param name=\"builder\">CosmosDBDatabase resource builder.</param>\n    /// <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();","sourceCodeStart":404,"sourceCodeEnd":440,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Azure.CosmosDB/AzureCosmosDBExtensions.cs#L404-L440","documentation":"AddContainerForPolyglot accepts a loosely-typed partitionKeyPaths parameter to support polyglot callers. At runtime it must be either a string (single path) or an IEnumerable<string>; any other type throws ArgumentException. This is a runtime type check because static typing cannot constrain the polyglot input.","triggerScenarios":"Calling AddContainerForPolyglot with partitionKeyPaths that is neither string nor IEnumerable<string>, e.g. an object[], List<object>, char, or a boxed non-string value.","commonSituations":"Invocation from other-language or generated code that builds the argument dynamically; passing a JSON-derived array typed as object[] instead of string[].","solutions":["Pass a single string path like \"/id\" or an IEnumerable<string> such as string[] or List<string>.","Convert generic collections with .Cast<string>().ToArray() before calling.","Normalize any dynamic input to IEnumerable<string> first and reject other types with your own validation."],"exampleFix":"// before\nobject partitionKeys = new object[] { \"/id\", \"/tenant\" }; // object[] is not IEnumerable<string>\ndb.AddContainerForPolyglot(\"orders\", partitionKeys, null);\n// after\nobject partitionKeys = new[] { \"/id\", \"/tenant\" }; // string[]\ndb.AddContainerForPolyglot(\"orders\", partitionKeys, null);","handlingStrategy":"type-guard","validationCode":"if (partitionKeyPaths is not string and not IEnumerable<string>) throw new ArgumentException(\"Partition key paths must be a string or a string collection.\");","typeGuard":"static bool IsValidPartitionKeyArg(object? o) => o is string or IEnumerable<string>;","tryCatchPattern":"try { db.AddContainerForPolyglot(\"orders\", rawArg, null); } catch (ArgumentException ex) when (ex.ParamName == \"partitionKeyPaths\") { /* coerce rawArg to string[] and retry */ }","preventionTips":["Always pass string or string[]/List<string> from polyglot callers.","Cast object collections with .Cast<string>().ToArray() first.","Document the accepted argument shape in caller code."],"tags":["cosmosdb","type-mismatch","polyglot"],"backgroundTag":"type-mismatch","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"}