ruvnet/ruflo · error · Error

browser/eval: script must not be empty

Error message

browser/eval: script must not be empty

What it means

Thrown by the browser/eval MCP tool handler when input.script is falsy or has length 0. The tool's JSON schema already marks 'script' as required, so this is the runtime guard behind the schema. It fires before any length-max or dangerous-pattern checks.

Source

Thrown at v3/@claude-flow/browser/src/mcp-tools/browser-tools.ts:668

    category: 'browser-eval',
    inputSchema: {
      type: 'object',
      properties: {
        session: { type: 'string', description: 'Session ID' },
        script: {
          type: 'string',
          description: `JavaScript code to execute (max ${MAX_EVAL_SCRIPT_LENGTH} chars)`,
          maxLength: MAX_EVAL_SCRIPT_LENGTH,
        },
      },
      required: ['script'],
    },
    handler: async (input) => {
      const script = input.script as string;

      // Validate script length
      if (!script || script.length === 0) {
        throw new Error('browser/eval: script must not be empty');
      }
      if (script.length > MAX_EVAL_SCRIPT_LENGTH) {
        throw new Error(`browser/eval: script exceeds maximum length of ${MAX_EVAL_SCRIPT_LENGTH} characters`);
      }

      // Check for dangerous patterns
      for (const pattern of DANGEROUS_EVAL_PATTERNS) {
        if (pattern.test(script)) {
          throw new Error(`browser/eval: script contains disallowed pattern: ${pattern.source}`);
        }
      }

      // Audit log
      console.info(`[browser/eval] Executing script (${script.length} chars) in session ${input.session || 'default'}`);

      const adapter = getAdapter(input.session as string);
      return adapter.eval({ script });
    },

View on GitHub (pinned to 6b01dc5a68)

Solutions

  1. Ensure the script argument is a non-empty string before invoking browser/eval.
  2. If the script is generated, fall back to a safe no-op or skip the call rather than sending an empty string.
  3. Validate at the caller boundary with a type guard or zod schema mirroring the tool's contract.

Example fix

// before
await evalTool.handler({ script: code ?? '' }); // throws 62 when code is null

// after
if (typeof code === 'string' && code.length > 0) {
  await evalTool.handler({ script: code });
}
Defensive patterns

Strategy: validation

Validate before calling

function isNonEmptyScript(s) {
  return typeof s === 'string' && s.length > 0;
}
if (!isNonEmptyScript(input.script)) throw new Error('script required');

Type guard

function isNonEmptyScript(s) { return typeof s === 'string' && s.length > 0; }

Try / catch

null

Prevention

When it happens

Trigger: Invoking the browser/eval tool with script: '', script: undefined, script: null, or omitting the field entirely (when the MCP transport does not enforce required fields).

Common situations: An LLM tool call that templated an empty expression; a caller passing a variable that evaluated to undefined; a test fixture that forgets to populate the script field.

Related errors


AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12). Data as JSON: /api/errors/0a257c3bb625887d. Report an issue: GitHub.