{"record":{"id":"ab486376b27cd9d7","repo":"microsoft/aspire","slug":"deno-permission-values-cannot-be-null-or-empty","errorCode":null,"errorMessage":"Deno permission values cannot be null or empty.","messagePattern":"Deno permission values cannot be null or empty\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.JavaScript/DenoHostingExtensions.cs","lineNumber":76,"sourceCode":"            Kind = kind,\n            Deny = deny,\n            Values = snapshot,\n        };\n\n        // Deno delimits permission values with commas and offers no escape syntax, so a single value containing a\n        // 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.","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.JavaScript/DenoHostingExtensions.cs#L58-L94","documentation":"AddDenoPermission rejects null or empty strings in the permission values array because Deno would render them as a bare trailing '=' (e.g. --allow-read=), which older Deno treated oddly and Deno 2.9 rejects outright. The library fails at call time with ArgumentException instead of producing a command Deno refuses at startup.","triggerScenarios":"Calling WithDenoAllow/WithDenoDeny (e.g. WithDenoAllow(DenoPermissionKind.Read, \"\", \"path\")) with any null or \"\" entry in the params array, commonly from splitting an empty or comma-joined config string into values.","commonSituations":"Splitting an environment-variable or appsettings value like \"\" or \",,\" into permission values; conditionally passing an uninitialized string variable into the params array.","solutions":["Filter out null/empty entries before calling: values.Where(v => !string.IsNullOrEmpty(v)).ToArray().","Fix the config source so empty segments are not produced (skip empty entries when splitting).","If you intentionally want the permission granted with no paths, omit the values entirely rather than passing \"\"."],"exampleFix":"// before\nresource.WithDenoAllow(DenoPermissionKind.Read, config.Split(','));\n// after\nvar values = config.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);\nif (values.Length > 0) resource.WithDenoAllow(DenoPermissionKind.Read, values);","handlingStrategy":"validation","validationCode":"if (values.Any(v => string.IsNullOrEmpty(v))) throw new ArgumentException(\"Deno permission values must be non-empty strings.\");","typeGuard":null,"tryCatchPattern":"try { resource.WithDenoAllow(kind, values); } catch (ArgumentException ex) when (ex.ParamName == \"values\") { /* report offending config entry */ }","preventionTips":["Always use RemoveEmptyEntries when splitting permission lists","Sanitize config-derived string arrays before passing to params APIs","Add unit tests covering empty config values"],"tags":["argument-exception","deno","validation","empty-value"],"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"}