denoland/deno · error · TypeError

Failed to execute 'query' on 'Permissions': descriptor requi

Error message

Failed to execute 'query' on 'Permissions': descriptor required

What it means

The desktop runtime's Permissions.query implementation requires a descriptor object. `descriptor == null` or a non-object (string, number) throws this TypeError before any permission name is read.

Source

Thrown at cli/rt/desktop.rs:653

    set onchange(v) { this.#onchange = typeof v === "function" ? v : null; }
  }

  function laufeyToPermissionsApiState(s) {
    // Spec maps "prompt" through verbatim; "unsupported" has no spec
    // analog so we return "denied" — query() shouldn't throw, but we
    // shouldn't lie and say "granted" either.
    switch (s) {
      case "granted": return "granted";
      case "denied": return "denied";
      case "prompt": return "prompt";
      default: return "denied";
    }
  }

  const permissionsImpl = {
    async query(descriptor) {
      if (descriptor == null || typeof descriptor !== "object") {
        throw new TypeError(
          "Failed to execute 'query' on 'Permissions': descriptor required",
        );
      }
      const name = String(descriptor.name);
      if (name === "notifications") {
        // No side effects per spec — never call request_*.
        const s = await op_desktop_query_notification_permission();
        // Keep Notification.permission's cache in sync: a permissions.query
        // result is authoritative and lets the synchronous getter report
        // a current value without us needing a second roundtrip.
        if (s !== "unsupported") {
          cachedNotificationPermission = laufeyToNotificationPermission(s);
        }
        return new PermissionStatus(name, laufeyToPermissionsApiState(s));
      }
      // Unknown / unrouted name. Chrome returns "denied" for descriptors
      // it doesn't recognize; mimic that rather than throwing.
      return new PermissionStatus(name, "denied");

View on GitHub (pinned to 89f33cbef2)

Solutions

  1. Call query({ name: 'notifications' }).
  2. If the descriptor comes from data, validate it is an object with a name property before calling.

Example fix

// before
const s = await navigator.permissions.query('notifications');
// after
const s = await navigator.permissions.query({ name: 'notifications' });
Defensive patterns

Strategy: validation

Validate before calling

const descriptor = { name: 'notifications' };
if (typeof descriptor !== 'object' || descriptor === null) {
  throw new Error('permissions.query needs { name: ... }');
}
await navigator.permissions.query(descriptor);

Type guard

function isPermissionDescriptor(v: unknown): v is { name: string } {
  return typeof v === 'object' && v !== null &&
    typeof (v as { name?: unknown }).name === 'string';
}

Prevention

When it happens

Trigger: navigator.permissions.query() with no argument, .query(null), or .query('notifications') — the name must be wrapped in an object: { name: 'notifications' }.

Common situations: Passing the permission name as a bare string instead of a descriptor object; copy-paste from APIs that take string parameters.

Related errors


AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16). Data as JSON: /api/errors/cecac2e312c086c7. Report an issue: GitHub.