SeleniumHQ/selenium · error · WebDriverError

${response.error}

Error message

${response.error}

What it means

Thrown by ScriptManager.removePreloadScript() when the BiDi response to script.removePreloadScript contains an 'error' field. Unlike most commands that rely on the transport layer for errors, this method explicitly checks for response.error and wraps it in a WebDriverError. The actual message is the remote-end error string, so the root cause is server-side (the script id was invalid/unknown, or the session rejected the command).

Source

Thrown at javascript/selenium-webdriver/bidi/scriptManager.js:330

    return response.result.script
  }

  /**
   * Removes a preload script.
   *
   * @param {string} script - The ID for the script to be removed.
   * @returns {Promise<any>} - A promise that resolves with the result of the removal.
   * @throws {WebDriverError} - If an error occurs during the removal process.
   */
  async removePreloadScript(script) {
    const params = { script: script }
    const command = {
      method: 'script.removePreloadScript',
      params,
    }
    let response = await this.bidi.send(command)
    if ('error' in response) {
      throw new WebDriverError(response.error)
    }
    return response.result
  }

  getCallFunctionParams(
    targetType,
    id,
    sandbox,
    functionDeclaration,
    awaitPromise,
    argumentValueList = null,
    thisParameter = null,
    resultOwnership = null,
  ) {
    const params = {
      functionDeclaration: functionDeclaration,
      awaitPromise: awaitPromise,
    }

View on GitHub (pinned to aa36b38e69)

Solutions

  1. Verify the script id is the exact value returned by addPreloadScript and that it has not already been removed.
  2. Track added preload script ids in a Set and guard removal to avoid double-removal.
  3. Ensure the BiDi session and the relevant browsing context are still alive before removing.
  4. Wrap the call in try/catch and treat 'no such script' errors as non-fatal if idempotent removal is acceptable for your flow.

Example fix

// before
await scriptManager.removePreloadScript(cachedId) // cachedId may be stale

// after
const added = new Set()
const id = await scriptManager.addPreloadScript(...)
added.add(id)
// later
if (added.has(id)) {
  try { await scriptManager.removePreloadScript(id) } catch (e) { /* already gone */ }
  added.delete(id)
}
Defensive patterns

Strategy: try-catch

Validate before calling

const addedScripts = new Set()
// after addPreloadScript: addedScripts.add(id)
if (!addedScripts.has(scriptId)) {
  throw new Error(`script id ${scriptId} was not added or already removed`)
}

Try / catch

try {
  await scriptManager.removePreloadScript(id)
  addedScripts.delete(id)
} catch (e) {
  if (e instanceof WebDriverError && /no such|unknown script/i.test(e.message)) {
    addedScripts.delete(id) // already removed, treat as success
  } else throw e
}

Prevention

When it happens

Trigger: Calling removePreloadScript(scriptId) with an id that was never added, an id that was already removed, an id from a different session, or after the BiDi session was closed.

Common situations: Removing a preload script twice; storing the wrong id; calling remove after the context/session that owned it was destroyed; timing issues where the add call failed but the id was cached.

Related errors


AI-assisted analysis of SeleniumHQ/selenium@aa36b38e69 (2026-08-14). Data as JSON: /api/errors/7145d7ed2941b4b0. Report an issue: GitHub.