CherryHQ/cherry-studio · warning · Error

Unknown script error

Error message

Unknown script error

What it means

Returned when a CDP Runtime.evaluate call has exceptionDetails but exceptionDetails.exception?.description is absent/falsy, so there is no descriptive message to surface. The code falls back to the literal string 'Unknown script error'. This is a defensive default for malformed or terse CDP exception payloads.

Solutions

  1. Inspect the full evalResult.exceptionDetails object (text, exception.type, exception.value, stackTrace) rather than only exception.description.
  2. Simplify the expression and run a trivial probe (e.g. 1+1) to confirm the page is evaluable at all.
  3. Check page CSP headers and contextIsolation/sandbox settings that may strip exception detail.
  4. Wrap the evaluated expression in try/catch on the page so it returns a structured error instead of throwing.

Example fix

// before
const message = evalResult.exceptionDetails.exception?.description || 'Unknown script error'
logger.warn('Runtime.evaluate raised exception', { message })
throw new Error(message)

// after — extract the richest available detail
const d = evalResult.exceptionDetails
const message =
  d.exception?.description ||
  d.text ||
  (d.exception ? `${d.exception.type}: ${JSON.stringify(d.exception.value)}` : null) ||
  'Unknown script error'
logger.warn('Runtime.evaluate raised exception', { message, details: d })
throw new Error(message)
Defensive patterns

Strategy: try-catch

Validate before calling

// Probe eval viability before running the real expression
async function canEvaluate(controller, tabId) {
  try {
    const probe = await controller.eval(tabId, '1+1')
    return probe === 2 || probe === '2'
  } catch {
    return false
  }
}

Try / catch

// Extract the richest available CDP exception detail
function describeEvalError(evalResult) {
  const d = evalResult?.exceptionDetails
  if (!d) return null
  return d.exception?.description || d.text || (d.exception ? `${d.exception.type}: ${JSON.stringify(d.exception.value)}` : null) || 'Unknown script error'
}

Prevention

When it happens

Trigger: Executing JavaScript in a browser tab via the eval tool where the page-side script throws, but the CDP exception object lacks a description field — e.g. a thrown non-Error value, a security/csp rejection, or a detached target.

Common situations: Page CSP blocks evaluation; script throws a primitive (throw 'x') that has no Error.description; the target navigated or was destroyed mid-eval producing a bare exceptionDetails; sandbox context isolation rejecting the expression.

Related errors


AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12). Data as JSON: /api/errors/340ab569cf4e89d4. Report an issue: GitHub.

Appendix: source

Thrown at src/main/ai/mcp/servers/browser/controller.ts:716

      expression: code,
      awaitPromise: true,
      returnByValue: true
    })

    try {
      const result = await Promise.race([
        evalPromise,
        new Promise((_, reject) => {
          timeoutHandle = setTimeout(() => reject(new Error('Execution timed out')), timeout)
        })
      ])

      const evalResult = result

      if (evalResult?.exceptionDetails) {
        const message = evalResult.exceptionDetails.exception?.description || 'Unknown script error'
        logger.warn('Runtime.evaluate raised exception', { message })
        throw new Error(message)
      }

      const value = evalResult?.result?.value ?? evalResult?.result?.description ?? null
      return value
    } finally {
      if (timeoutHandle) clearTimeout(timeoutHandle)
    }
  }

  public async reset(privateMode?: boolean, tabId?: string) {
    if (privateMode !== undefined && tabId) {
      const windowKey = this.getWindowKey(privateMode)
      const windowInfo = this.windows.get(windowKey)
      if (windowInfo) {
        this.closeTabInternal(windowInfo, tabId)
        windowInfo.tabs.delete(tabId)

        // If no tabs left, close the window

View on GitHub (pinned to 726446b54c)