Skip to main content

Debugging and Troubleshooting

Debug mode

When the screenshot/Full report modules aren't enough to see what happened, Debug mode (Advanced setup) makes the task itself capture richer evidence automatically on every run — no need to reproduce the failure manually.

Turning it on adds trace: 'on-first-retry', screenshot: 'only-on-failure' and video: 'retain-on-failure' to the run (the same config the manual flow below uses), and, once the run finishes, leaves in the Debug directory:

  • The screenshot, trace and video Playwright captured, under <debug_directory>/test-results/<test>/.
  • A report.md summary (status, phases, errors) written by the plugin itself.

Where the output ends up. The Debug directory is always an absolute path, and it always ends up centralized on the Discovery server — never on the console, and never left stranded on a remote worker:

  • worker_mode = local: the Discovery server is the machine that runs Docker, so the directory is simply created there directly.
  • worker_mode = remote: Docker still runs over SSH on the remote host as usual, but once the run finishes the plugin downloads the whole directory back onto the Discovery server (reusing the same SSH session already open to drive Docker there) and removes the remote copy — only after the local copy is confirmed on disk, so a failed download never loses data.

One run, one folder. The directory is wiped and recreated on every execution — it is not appended to, so it always holds exactly the latest run's artifacts, never a growing pile of old ones.

Permissions. Whatever ends up in the directory (including subfolders Playwright itself creates) is left world-readable/writable, so it can be read, moved or cleaned up by any user afterward — including a tool other than the Discovery server.

The _taskid_ placeholder

The default Debug directory is /var/spool/pandora/data_in/discovery/tmp/playwright/_taskid_. _taskid_ is resolved by the plugin at runtime to md5(id_rt) of the task that produced it — the exact same value Discovery itself computes internally as its __taskMD5__ macro. This is deliberate: it means the debug output of any task can be located from outside the plugin (e.g. from a console extension) just by knowing that task's id_rt and recomputing md5($id_rt) — no need to ask the plugin or read any extra state.

_taskid_ only works inside this one field; it is not a general Discovery macro and has no effect anywhere else in the task configuration. Replace the default with a fixed absolute path instead if the same folder should be reused across runs regardless of which task produced them.

Viewing the evidence from the console

The WUX Transactions extension (Monitoring → Views → WUX Transactions) reads this evidence directly. Any transaction whose test was captured by a debug-enabled task gets a Playwright debug button next to its status, opening a viewer with the failure video, the failure screenshot (click to zoom), Playwright's error context and the full run report, both rendered from Markdown.

Consequences visible in the UI:

  • A transaction produced by several tasks shows Playwright debug (N tasks), and the viewer lists one block per task, each with its own capture timestamp, browser and worker mode. It is also flagged with a Shared by N tasks badge, a counter in the overview and a warning banner, because those tasks overwrite each other on the same modules — see Agent identity and shared transactions.
  • Only the latest capture of each task exists, since the debug directory is wiped on every execution.
  • A transaction shows no button when no debug-enabled task has run it yet.
  • Artifacts are streamed through an authenticated console endpoint that re-validates the file against the task's own debug directory and enforces the task's group ACL, so evidence is never served from an arbitrary path.

The extension never uses a fixed path: it reads each task's own Debug directory field. Changing that field on a task is enough for the extension to follow it — there is nothing to configure on the extension side.

Agent identity and shared transactions

A Playwright agent is named a + md5(<agent prefix> + <test title>). Because the task plays no part in that name, two Discovery tasks running a test with the same title report to the same agent, and each run overwrites the previous one on the same modules. That is a monitoring-data problem, not only a debug inconvenience: Global status would alternate between whatever each task measured.

The extension surfaces it — badge, overview counter and banner — but the fix is on the task: give each one its own Prefix for agents created (for example prod- and dev-) so they become separate agents. Leaving the prefix empty keeps the original naming, so existing agents are never orphaned.

Note the detection only covers tasks with debug mode enabled, since the task→agent link lives in manifest.json. Two colliding tasks where one has debug off still collide, but the console cannot see it.

When the evidence is not visible

Debug-enabled tasks whose evidence cannot be read are listed at the top of the extension, collapsed, with the task, its directory and the reason — rather than silently disappearing. The reasons and what causes them:

**Reason shown****When it happens**
No absolute debug directory is set on the taskDebug mode is on but the directory field was left empty, or holds a relative path. The task also fails at execution time, since the runner validates it — so it is producing nothing at all.
The debug directory does not exist on this consoleTwo very different causes. Either the task **has not run yet** since debug was enabled (it resolves itself on the next execution), or **the console and the Discovery server are different hosts**: the path is valid on the server but the console cannot see that filesystem. The latter is an environment matter — share `data_in` over NFS or sync it so the console reaches the same path.
The directory exists but holds no manifest.jsonThe task ran but left no manifest. Typically it is running an **older build of the plugin** (predating `manifest.json`), or the run **failed before capturing anything** (Docker image missing, SSH down). In `remote` mode it can also mean the **SCP fetch failed**, in which case the evidence is intact on the worker, since the runner deliberately keeps the remote copy when the download does not land.
The manifest exists but could not be read or is malformedPermissions or a corrupt file — a directory moved by hand, or a run interrupted mid-write. The runner leaves everything world-readable, so this is rare.

This report is shown once for the whole view, not next to a transaction, and that is a consequence of the design: without a manifest there is no way to know which transactions that task feeds.

Manual interactive debugging

Run the test interactively inside the same image the plugin uses, with Playwright's HTML report (trace + failure video) served from the container. The image ships playwright.config.debug.ts (in /pandora) preconfigured with trace: 'on-first-retry', screenshot: 'only-on-failure', video: 'retain-on-failure', and an HTML reporter bound to 0.0.0.0:9323.

docker run -it --rm \
  -v "$(pwd)/test.spec.ts:/pandora/test.spec.ts" \
  -p 9323:9323 \
  pandorafms/pandora_playwright:noble bash

# inside the container:
npx playwright test test.spec.ts --config=playwright.config.debug.ts --browser=chromium --timeout=30000
npx playwright show-report --host 0.0.0.0 --port 9323

With -p 9323:9323 published, open http://localhost:9323 on the host to browse the report: per-step results, the trace viewer, and the video of the failure.

Troubleshooting

  • "Playwright produced no report" — the test failed to run (syntax error, bad import, missing browser). Run with -v and read the docker exec stderr.
  • Screenshot shows as text, not an image — the value must be generic_data_string with a data:image/png;base64, prefix; check the plugin build includes this.
  • Cannot find module '@playwright/test' — the test must run from /pandora inside the image so Node resolves node_modules; the plugin copies it to /pandora/task.spec.ts for this reason.
  • Agents land in the wrong group (standalone -x mode) — Pandora agent XML expects the group name, not the numeric id. The Discovery monitoring_data path uses the numeric id_group correctly.
  • A later phase still shows "ok" after an earlier failure — a failed hard assertion aborts the run, so later phases keep their previous value. Use expect.soft() if every phase must be measured on every run.
  • net::ERR_CERT_AUTHORITY_INVALID — see Self-signed certificates.
  • Debug mode fails immediately with a Docker "invalid volume name" / "use absolute path" error — the Debug directory must be an absolute path (starting with /). Docker rejects a relative bind-mount path outright; the plugin also validates this itself and fails fast with an explicit error before ever calling Docker.
  • Debug mode fails with "debug_directory is required when debug is enabled" — the Advanced setup form cannot express a conditionally-mandatory field, so an empty Debug directory with Debug mode on is only caught by the plugin at run time, not by the console form.
  • No "Playwright debug" button on a transaction, even with debug enabled — check the report at the top of the WUX Transactions extension: it lists every debug-enabled task whose evidence could not be read, with the reason. See When the evidence is not visible. The usual cases are a task that has not run yet, or a console that cannot reach the Discovery server's filesystem.
  • The extension reports "directory does not exist on this console" — expected when the console and the Discovery server are separate hosts, since the artifacts live on the server. Share data_in over NFS or sync it; there is nothing to configure in the extension, which always follows each task's own Debug directory field.
  • The extension reports "holds no manifest.json" — the task is very likely running an older plugin build. Remember a Pandora install keeps two copies of a Discovery plugin: <homedir>/attachment/discovery/<short_name>/ (console) and <remote_config>/discovery/<short_name>/ (typically /var/spool/pandora/data_in/discovery/<short_name>/), and it is the second one the Discovery server actually executes. Updating only the first leaves the old binary running with no visible error.
  • A transaction is flagged "Shared by N tasks" — several Discovery tasks run a test with that same title and therefore write to the same agent, overwriting each other. Set a different Prefix for agents created on each task. See Agent identity and shared transactions.