denoland/deno · error · DOMException

NotSupportedError

NotSupportedError

Error message

'name' must not start with '-'

What it means

The Web Locks API reserves lock names beginning with a hyphen ('-') for internal use, so LockManager.request rejects them with a DOMException named NotSupportedError, thrown from ext/web/locks.js after option conversion but before acquiring anything. The check uses startsWith on the raw name string. Nothing was locked when this throws.

Source

Thrown at ext/web/locks.js:124

    if (arguments.length === 2) {
      options = {};
      callback = optionsOrCallback;
    } else {
      options = optionsOrCallback;
    }

    if (typeof callback !== "function") {
      throw new TypeError("callback must be a function");
    }

    options = webidl.converters.LockOptions(
      options,
      prefix,
      "Argument 2",
    );

    if (StringPrototypeStartsWith(name, "-")) {
      throw new DOMException(
        "'name' must not start with '-'",
        "NotSupportedError",
      );
    }
    if (options.steal && options.ifAvailable) {
      throw new DOMException(
        "'steal' and 'ifAvailable' are exclusive",
        "NotSupportedError",
      );
    }
    if (options.steal && options.mode !== "exclusive") {
      throw new DOMException(
        "'mode' must be 'exclusive' if 'steal' is specified",
        "NotSupportedError",
      );
    }
    if (options.signal && (options.steal || options.ifAvailable)) {
      throw new DOMException(

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Rename the lock so it does not start with '-', e.g. 'mylock' or 'app:mylock'.
  2. If names derive from user input, sanitize: name.replace(/^-+/, "").
  3. Validate generated names with a check like name.startsWith('-') before calling request.
  4. Pick a namespace separator that cannot appear at position 0, such as ':' or '__'.

Example fix

// before
navigator.locks.request("-job:" + id, cb);

// after
navigator.locks.request("job:" + id, cb);
Defensive patterns

Strategy: validation

Validate before calling

function lockName(name) {
  const n = name.replace(/^-+/, "");
  if (n.startsWith("-")) throw new Error(`invalid lock name: ${name}`);
  return n;
}
navigator.locks.request(lockName(raw), cb);

Type guard

function isValidLockName(name) {
  return typeof name === "string" && name.length > 0 && !name.startsWith("-");
}

Try / catch

try { await navigator.locks.request(name, cb); } catch (e) { if (e.name === "NotSupportedError" && e.message.includes("'-'")) await navigator.locks.request(name.replace(/^-+/, ""), cb); else throw e; }

Prevention

When it happens

Trigger: navigator.locks.request("-mylock", cb); names built from user input or generated IDs that start with '-'; prefixing names with '-' as a namespace convention ('-app:resource').

Common situations: Auto-generated lock keys from slugs or CLI-style flags ('--job-42'); copying a naming scheme from a queue/redis library where '-' prefixes are allowed; concatenating '-' separators after an empty first segment, producing a leading '-'.

Related errors


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