denoland/deno · error · TypeError
The provided value "${desc?.name}" is not a valid permission
Error message
The provided value "${desc?.name}" is not a valid permission name. What it means
Deno.permissions.request/requestSync prompt the user (or resolve against flags when prompts are disabled) and validate the descriptor first: a non-null object whose `name` is one of read, write, net, env, sys, run, ffi, import. Otherwise they throw TypeError(`The provided value "${desc?.name}" is not a valid permission name.`) — note this variant's message ends with a period; the async request() surfaces it as a rejection.
Source
Thrown at runtime/js/10_permissions.js:258
}
formDescriptor(desc);
const status = opRevoke(desc);
return cache(desc, status);
}
request(desc) {
try {
return PromiseResolve(this.requestSync(desc));
} catch (error) {
return PromiseReject(error);
}
}
requestSync(desc) {
if (!isValidDescriptor(desc)) {
throw new TypeError(
`The provided value "${desc?.name}" is not a valid permission name.`,
);
}
formDescriptor(desc);
const status = opRequest(desc);
return cache(desc, status);
}
}
const permissions = new Permissions(illegalConstructorKey);
/** Converts all file URLs in FS allowlists to paths. */
function serializePermissions(permissions) {
if (typeof permissions == "object" && permissions != null) {
const serializedPermissions = { __proto__: null };
for (View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Use exactly one of: read, write, net, env, sys, run, ffi, import, with the matching per-name field (path, host, command, variable, kind)
- Validate the descriptor before prompting (see defense) so users never see a crash mid-flow
- For dynamic names, verify against a const list and surface a configuration error
- Catch the rejection from the async form when descriptors are external input
Example fix
// before
await Deno.permissions.request({ name: 'network' });
// after
await Deno.permissions.request({ name: 'net', host: 'api.example.com' }); Defensive patterns
Strategy: type-guard
Validate before calling
const PERMISSION_NAMES = ['read', 'write', 'net', 'env', 'sys', 'run', 'ffi', 'import'];
function isPermissionDescriptor(d) {
return typeof d === 'object' && d !== null &&
PERMISSION_NAMES.includes(d.name);
}
if (!isPermissionDescriptor(desc)) {
throw new Error('invalid permission request');
}
const status = await Deno.permissions.request(desc); Type guard
function isPermissionDescriptor(d) {
return typeof d === 'object' && d !== null &&
['read', 'write', 'net', 'env', 'sys', 'run', 'ffi', 'import'].includes(d.name);
} Try / catch
try {
const status = await Deno.permissions.request(desc);
} catch (e) {
if (e instanceof TypeError && e.message.includes('not a valid permission name')) {
// bad descriptor — surface a configuration error to the user
} else {
throw e;
}
} Prevention
- Validate names before prompting so users never hit a crash mid-prompt
- Remember this variant's message ends with a period — match loosely (includes) not exactly
- request() rejects asynchronously; wrap user-facing flows in try/catch around the await
When it happens
Trigger: `Deno.permissions.request({ name: 'network' })`; requesting with a typo like 'writ'; passing a non-object or no descriptor; mapping CLI flag strings directly to descriptor names.
Common situations: Interactive CLIs requesting scoped access at runtime; permission prompts in tools run with --no-prompt where a bad name fails fast instead of prompting.
Related errors
- The provided value "${desc?.name}" is not a valid permission
- Invalid port: '${maybePort}'
- Illegal constructor
- Failed to execute 'query' on 'Permissions': descriptor requi
- BenchContext::start() has already been invoked
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/c04921247c44f59a.
Report an issue: GitHub.