{"record":{"id":"ae5d6c3df84914c2","repo":"microsoft/aspire","slug":"the-value-value-cannot-contain-a-comma-deno-separates-flag","errorCode":null,"errorMessage":"The value '{value}' cannot contain a comma. Deno separates {flag} values with commas and provides no way to escape them, so this value would be interpreted as multiple permissions. Pass each value as a separate argument.","messagePattern":"The value '(.+?)' cannot contain a comma\\. Deno separates (.+?) values with commas and provides no way to escape them, so this value would be interpreted as multiple permissions\\. Pass each value as a separate argument\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.JavaScript/DenoHostingExtensions.cs","lineNumber":82,"sourceCode":"        // comma silently becomes several permissions. Verified on Deno 2.9.0: `--allow-read=data,secret` intended as\n        // one directory named \"data,secret\" instead grants `data` and `secret` separately, so the requested path is\n        // denied while unrelated paths are granted. Reject it here rather than emit a command line that means\n        // something other than what the caller asked for.\n        //\n        // An empty params array intentionally emits an unscoped flag, but an individual null or empty value emits\n        // `--allow-read=` (or the equivalent permission) and Deno 2.9 rejects it. Do not trim values: Deno accepts\n        // whitespace as a permission value.\n        foreach (var value in snapshot)\n        {\n            if (string.IsNullOrEmpty(value))\n            {\n                throw new ArgumentException(\"Deno permission values cannot be null or empty.\", nameof(values));\n            }\n\n            if (value.Contains(','))\n            {\n                var flag = permission.Deny ? $\"--deny-{permission.Name}\" : $\"--allow-{permission.Name}\";\n                throw new ArgumentException($\"The value '{value}' cannot contain a comma. Deno separates {flag} values with commas and provides no way to escape them, so this value would be interpreted as multiple permissions. Pass each value as a separate argument.\", nameof(values));\n            }\n        }\n\n        var annotation = GetOrAddDenoAnnotation(builder);\n        annotation.Permissions.Add(permission);\n        return builder;\n    }\n\n    // ---- Blanket permission -----------------------------------------------------------------\n\n    /// <summary>\n    /// Controls the blanket <c>-A</c>/<c>--allow-all</c> grant.\n    /// </summary>\n    /// <param name=\"builder\">The Deno app resource builder.</param>\n    /// <param name=\"enabled\">\n    /// Whether to emit <c>-A</c>/<c>--allow-all</c>. Pass <see langword=\"false\"/> to grant only permissions\n    /// configured with <see cref=\"WithDenoAllow\"/>.\n    /// </param>","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.JavaScript/DenoHostingExtensions.cs#L64-L100","documentation":"Deno CLI permission flags accept comma-separated values and provide no escaping, so a value containing a comma (e.g. \"/a,/b\") would silently be interpreted as two separate permissions. The library throws ArgumentException to force each value to be passed as its own argument.","triggerScenarios":"Calling WithDenoAllow/WithDenoDeny with a value string containing a comma, e.g. WithDenoAllow(DenoPermissionKind.Read, \"/tmp,/var\") instead of passing \"/tmp\" and \"/var\" separately.","commonSituations":"Passing a pre-joined comma-separated list from config or CLI args directly into the API; concatenating paths with ',' when building values programmatically.","solutions":["Split the string on ',' and pass each piece as a separate argument: WithDenoAllow(kind, list.Split(',')).","In config, keep values as a real list (JSON array / repeated keys) rather than a comma-joined string.","If a path legitimately contains a comma, verify Deno supports it via another mechanism — there is no escape; restructure (e.g. allow the parent directory)."],"exampleFix":"// before\nresource.WithDenoAllow(DenoPermissionKind.Read, \"/tmp,/var\");\n// after\nresource.WithDenoAllow(DenoPermissionKind.Read, \"/tmp\", \"/var\");","handlingStrategy":"validation","validationCode":"if (values.Any(v => v.Contains(','))) throw new ArgumentException(\"Pass each Deno permission value as a separate argument; commas are not escapable.\");","typeGuard":null,"tryCatchPattern":"try { resource.WithDenoAllow(kind, values); } catch (ArgumentException ex) when (ex.ParamName == \"values\") { /* split values and retry or report */ }","preventionTips":["Never pre-join Deno permission values with commas","Model multi-value permissions as arrays in configuration","Document that Deno commas are value separators, not data"],"tags":["argument-exception","deno","format","cli-arguments"],"backgroundTag":"invalid-argument-format","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"}