ruvnet/ruflo · 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 in @claude-flow/browser when the required 'script' input is missing, undefined, or an empty string. The JSON-Schema for the tool only marks 'script' as required (presence), so an empty string passes schema checks and this handler-level guard rejects it before any dangerous-pattern scanning or adapter dispatch happens.

Solutions

  1. Ensure the script string is non-empty before invoking the tool (trim and length-check at the call site)
  2. Fix the upstream generator/placeholder that produced the empty script string
  3. If empty input is legitimate in your flow, short-circuit with a no-op instead of calling the tool

Example fix

// before
await tools.invoke('browser/eval', { script: extracted }); // extracted === ''

// after
const script = (extracted ?? '').trim();
if (script.length === 0) return { skipped: true, reason: 'no script extracted' };
await tools.invoke('browser/eval', { script });
Defensive patterns

Strategy: validation

Validate before calling

const script = String(input?.script ?? '').trim();
if (script.length === 0) {
  return { skipped: true, reason: 'empty script' };
}
await tools.invoke('browser/eval', { script });

Type guard

const isNonEmptyScript = (s: unknown): s is string => typeof s === 'string' && s.trim().length > 0;

Prevention

When it happens

Trigger: Invoking the browser/eval tool with script: '' or omitting script (undefined coerced by the `input.script as string` cast); passing whitespace-only or a variable that evaluated to empty at the call site.

Common situations: Template literals that render to empty when a placeholder is missing (script: `${userCode}` with userCode undefined); pipelines that chain eval after an extraction step which returned nothing; LLM-driven tool calls that emit an empty script argument.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: 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 fa13ee4ad6)