n8n-io/n8n · error · Error

No monitors available

Error message

No monitors available

What it means

Thrown by getPrimaryMonitor() in @n8n/computer-use when node-screenshots' MonitorClass.all() returns an empty array, meaning the host exposes no display devices. The function is used to pick a primary monitor for screen-capture tooling. The error is a bare `new Error(...)` (no n8n error class), so callers must match on message text.

Source

Thrown at packages/@n8n/computer-use/src/tools/monitor-utils.ts:6

import type { Monitor } from 'node-screenshots';

export async function getPrimaryMonitor(): Promise<Monitor> {
	const { Monitor: MonitorClass } = await import('node-screenshots');
	const monitors = MonitorClass.all();
	if (monitors.length === 0) throw new Error('No monitors available');
	return monitors.find((m) => m.isPrimary()) ?? monitors[0];
}

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Run the host with an attached display or start a virtual framebuffer: `xvfb-run -s '-screen 0 1920x1080x24' <cmd>`.
  2. If running in Docker, add a virtual display (`apt-get install xvfb` then launch Xvfb) or use an image that ships one.
  3. Confirm node-screenshots can enumerate monitors in isolation before invoking the tool: `import('node-screenshots').then(m => console.log(m.Monitor.all().length))`.
  4. Guard the call site: if getPrimaryMonitor() is optional, wrap it in try/catch and degrade gracefully or surface a user-facing 'no display' message.
  5. On Linux, ensure libx11, libxcb, libxrandr and a running X server (or Wayland compositor) are present.

Example fix

// before
const monitor = await getPrimaryMonitor();

// after
let monitor;
try {
  monitor = await getPrimaryMonitor();
} catch (err) {
  if (err instanceof Error && err.message === 'No monitors available') {
    throw new OperationalError('Screen capture is unavailable: no display detected. Run with an attached or virtual (Xvfb) display.');
  }
  throw err;
}
Defensive patterns

Strategy: validation

Validate before calling

import('node-screenshots').then(({ Monitor }) => {
  const count = Monitor.all().length;
  if (count === 0) {
    // surface 'no display' to the user; do not call getPrimaryMonitor()
  }
});

Type guard

function hasDisplay(monitors: unknown[]): monitors is { isPrimary(): boolean }[] {
  return Array.isArray(monitors) && monitors.length > 0;
}

Try / catch

try {
  const monitor = await getPrimaryMonitor();
} catch (err) {
  if (err instanceof Error && err.message === 'No monitors available') {
    // degrade or instruct user to attach/Xvfb a display
  } else throw err;
}

Prevention

When it happens

Trigger: Calling getPrimaryMonitor() on a headless server, a container without a virtual framebuffer (no Xvfb), a CI runner with no attached display, or an SSH session without X forwarding. Also triggered on OSes where node-screenshots cannot enumerate screens (missing native deps).

Common situations: Running the computer-use tool inside Docker/k8s without a display server; CI environments; remote SSH-only boxes; a misconfigured Xvfb; a Linux box where libx11/libxcb native libraries are absent so node-screenshots returns [].

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/c31bf9948249e083. Report an issue: GitHub.