jackwener/OpenCLI · error

browser drag is not supported by this browser backend

Error message

browser drag is not supported by this browser backend

What it means

The `browser drag` command feature-detects `page.drag` and throws this capability error when the backend lacks drag-and-drop support. Dragging requires low-level mouse event synthesis that limited drivers do not implement.

Source

Thrown at src/cli.ts:2250

        return;
      }
      const result = await page.uploadFiles(resolvedTarget, resolvedFiles.files, parsed.opts);
      console.log(JSON.stringify(result, null, 2));
    }));

  addBrowserTabOption(
    addPrefixedSemanticLocatorOptions(
      addPrefixedSemanticLocatorOptions(browser.command('drag'), 'from'),
      'to',
    )
      .argument('[source]', 'Numeric ref/CSS selector to drag from, or omit with --from-role/--from-name/etc.')
      .argument('[target]', 'Numeric ref/CSS selector to drop onto, or omit with --to-role/--to-name/etc.')
      .option('--from-nth <n>', 'When <source> is a multi-match CSS selector, pick the nth match (0-based)')
      .option('--to-nth <n>', 'When <target> is a multi-match CSS selector, pick the nth match (0-based)')
      .description('Drag one element to another — JSON envelope {dragged, source, target, source_matches_n, target_matches_n}'),
  )
    .action(browserAction(async (page, source, target, opts) => {
      if (typeof page.drag !== 'function') throw new Error('browser drag is not supported by this browser backend');
      const resolvedSource = await resolvePrefixedWriteTargetOrPrint(page, source, opts ?? {}, 'from', 'source');
      if (!resolvedSource) return;
      const resolvedTarget = await resolvePrefixedWriteTargetOrPrint(page, target, opts ?? {}, 'to', 'target');
      if (!resolvedTarget) return;
      const from = parseResolveFlag(opts?.fromNth, '--from-nth');
      if ('error' in from) {
        console.log(JSON.stringify({ error: { code: 'usage_error', message: from.error } }, null, 2));
        process.exitCode = EXIT_CODES.USAGE_ERROR;
        return;
      }
      const to = parseResolveFlag(opts?.toNth, '--to-nth');
      if ('error' in to) {
        console.log(JSON.stringify({ error: { code: 'usage_error', message: to.error } }, null, 2));
        process.exitCode = EXIT_CODES.USAGE_ERROR;
        return;
      }
      const result = await page.drag(resolvedSource, resolvedTarget, { from: from.opts, to: to.opts });
      console.log(JSON.stringify(result, null, 2));

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Switch to a backend implementing drag (Playwright/Puppeteer).
  2. Emulate drag via `browser eval` dispatching dragstart/dragover/drop events for HTML5 DnD.
  3. Update the driver/adapter to a version with drag support.

Example fix

// before
browser --backend minimal drag '#item' --to '#list'
// after
browser --backend playwright drag '#item' --to '#list'
Defensive patterns

Strategy: type-guard

Validate before calling

const page = await getBrowserPage();
if (typeof page.drag !== 'function') {
  throw new Error('Current backend cannot drag elements');
}

Type guard

function supportsDrag(page) {
  return typeof page?.drag === 'function';
}

Try / catch

try {
  await run(['browser', 'drag', src, '--to', dst]);
} catch (err) {
  if (String(err.message).includes('drag is not supported')) {
    await run(['browser', 'eval', html5DragScript(src, dst)]);
  } else throw err;
}

Prevention

When it happens

Trigger: Running `browser drag <source> --to <target>` (or with --to-role/--to-name) on a backend without a `drag` method.

Common situations: Minimal/custom browser drivers; HTML5 drag-and-drop pages where even supported backends may need eval-based workarounds.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/650f6e6026ee71a8. Report an issue: GitHub.