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

  1. Use exactly one of: read, write, net, env, sys, run, ffi, import, with the matching per-name field (path, host, command, variable, kind)
  2. Validate the descriptor before prompting (see defense) so users never see a crash mid-flow
  3. For dynamic names, verify against a const list and surface a configuration error
  4. 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

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


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/c04921247c44f59a. Report an issue: GitHub.