Skip to content
Draft, pre-release documentation

These are problems we have hit and can reproduce, each with the condition that triggers it and a workaround. Several of them fail without any error message. Most are in the session around the runtime, such as Chrome, the image or the Kasm viewer.

Chrome ignores the debugging port without --user-data-dir

Section titled “Chrome ignores the debugging port without --user-data-dir”
  • Condition: Chrome 136 or later, started with --remote-debugging-port but no --user-data-dir.
  • Symptom: Chrome starts normally but opens no DevTools port, and prints nothing about it. Every dom.* call returns a resolution error, “no CDP connection is attached”, a scenario that declares browser steps ends in test-error, and the /cdp/ passthrough answers 502.
  • Workaround: add --user-data-dir=<a directory> to APP_ARGS. APP_ARGS replaces the image’s default arguments, so repeat any you need, such as --start-maximized. See Compatibility.

file:// pages are blocked in Kasm’s browser images

Section titled “file:// pages are blocked in Kasm’s browser images”
  • Condition: navigating Chrome to a file:// URL in a kasmweb browser image. The image’s managed policy (/etc/opt/chrome/policies/managed/urlblocklist.json) blocks file://*.
  • Symptom: the tab lands on chrome-error://chromewebdata/, and every selector afterwards fails to match.
  • Workaround: serve the files over HTTP on loopback inside the session and navigate to that address. Leave the policy in place if you are testing the image as shipped.

The runtime attaches to the first tab Chrome lists

Section titled “The runtime attaches to the first tab Chrome lists”
  • Condition: more than one page is open in Chrome when the runtime attaches, for example an extension popup left open by an earlier run. The runtime always takes the first page target Chrome reports.
  • Symptom: cdp_* steps and dom.* calls act on the wrong page. report.json’s cdp.target_url shows which tab was attached.
  • Workaround: close popups and extra tabs before the run starts; a scenario that opens a popup can end by pressing Escape. Check cdp.target_url when browser steps fail on a page that looks right.

A screenshot straight after a browser step can show the previous page

Section titled “A screenshot straight after a browser step can show the previous page”
  • Condition: a scenario takes a visual judgement (observe: or expect:) immediately after a cdp_* step. A navigation returns when the page is committed, before it is painted.
  • Symptom: the judgement sees the page as it was before the step.
  • Workaround: put a wait step between the browser action and the visual check. Scenarios made only of browser steps are not affected.

The framebuffer is not the size you asked for

Section titled “The framebuffer is not the size you asked for”
  • Condition: any of: a nix image with VNC_RESOLUTION unset (the default is 1280x720); a stock image, which ignores VNC_RESOLUTION; a session requested through Kasm’s API without x_res and y_res, which default to 800x600 and overwrite VNC_RESOLUTION; a viewer that resized the session mid-run.
  • Symptom: clicks by fraction, vision-grounded clicks and baseline comparisons are wrong for the size the scenario was written at, with no error.
  • Workaround: pin the size and refuse viewer resizes as described in Session geometry. report.json records the real size as screen.

A person’s clicks land in the wrong place in a scaled viewer

Section titled “A person’s clicks land in the wrong place in a scaled viewer”
  • Condition: a person watches a fixed-size session in a browser window that is not exactly the framebuffer’s size, so the viewer shows the session stretched or shrunk.
  • Symptom: the person’s clicks reach the session at the page pixel rather than the screen pixel they aimed at. A click aimed at (512, 461) on a 1024x768 session shown at 1400x1000 arrived at (700, 600). Observed on 2026-09-24 with the chrome:nix image; clicks are exact at 1:1. The cause is not confirmed. The runtime’s own clicks go straight to the X server and are not affected.
  • Workaround: size the browser window so the viewer shows the session at exactly its framebuffer size. The 10-playwright-verify example in the SDK is a test that catches this at the viewer sizes you care about.

Judgments come back empty from a thinking model

Section titled “Judgments come back empty from a thinking model”
  • Condition: a model that reasons before answering, with a reply-length cap it can reach. The server then returns HTTP 200 with empty content instead of an error.
  • Symptom: screenshot judgements and grounded clicks return nothing, and after repeated failures the runtime may stop calling the model.
  • Workaround: keep KASM_RUNTIME_MAX_TOKENS_JUDGE at its default of 2000 or raise it, and make sure no proxy in front of the model sets a lower cap. Where the server offers a non-thinking mode, use it for judging.

The runtime stops using the model for the rest of the run

Section titled “The runtime stops using the model for the rest of the run”
  • Condition: judgement calls fail in a row, every retry used up, KASM_RUNTIME_MODEL_DISABLE_AFTER times (default 2). A model that is still thinking when KASM_RUNTIME_MODEL_TIMEOUT_S (default 90) runs out counts as a failure.
  • Symptom: the run finishes in deterministic-only mode and the report notes that the vision endpoint was degraded. Screenshots are still taken but nothing is judged, and a goal: scenario cannot continue. Over MCP, screen.judge, screen.ground and screen.ask return a resolution error for the rest of the session.
  • Workaround: fix the endpoint first. For a slow or shared server, raise KASM_RUNTIME_MODEL_TIMEOUT_S, KASM_RUNTIME_MODEL_ATTEMPTS or KASM_RUNTIME_MODEL_DISABLE_AFTER. See Operator file.

A person’s keystrokes are hidden while the runtime types

Section titled “A person’s keystrokes are hidden while the runtime types”
  • Condition: KASM_RUNTIME_OBSERVE_INPUT=true, and a person types in the viewer during an input.type or input.key call, or while a scenario’s typing step runs.
  • Symptom: those key events are recorded with private: true and no key or text, so input.wait_for does not match them. The input still reaches the session. The runtime hides them because what it types may be a credential.
  • Workaround: keep people and the runtime from typing at the same time. When a wait misses, look for private: true entries in its events to see why.

A fatal log line far back in a chatty log is missed

Section titled “A fatal log line far back in a chatty log is missed”
  • Condition: the line that shows the application failed is more than evidence.log_tail_lines lines (default 200) from the end of its log, or outside the last 512 KiB of the file.
  • Symptom: the scenario’s log_fatal patterns do not fire, and the line does not appear in the report’s log excerpts.
  • Workaround: raise KASM_RUNTIME_EVIDENCE_LOG_TAIL_LINES. The 512 KiB window is fixed.

Registering the port map does nothing with too few permissions

Section titled “Registering the port map does nothing with too few permissions”
  • Condition: registering the runtime’s port map on an image (the SDK helper’s ensure-port-map) with an API key that has IMAGES_MODIFY but not IMAGES_MODIFY_RESOURCES. Kasm restricts an image’s run_config, where the port map lives.
  • Symptom: the call succeeds but the port map is not saved, so the session’s MCP endpoint cannot be reached through Kasm.
  • Workaround: use a key with IMAGES_VIEW, IMAGES_MODIFY and IMAGES_MODIFY_RESOURCES. The SDK helper’s bootstrap-api-key creates one with exactly those.