Hmbown/CodeWhale · error · ExecError
output path must be an absolute filename
Error message
output path must be an absolute filename
What it means
`outputPath` validates that every file the Linux backend writes (screenshots, recordings) is an absolute path string containing no NUL byte. Relative paths and non-string inputs are rejected so files land in a deterministic location regardless of the backend process's working directory.
Solutions
- Resolve the path to absolute before calling: `path.resolve("shot.png")`.
- Use path.join(os.homedir(), ...) or another absolute base directory.
- Validate the input is a non-empty string before passing it.
Example fix
// before
await backend.screenshot({ file: "shot.png" }); // throws
// after
import path from "node:path";
await backend.screenshot({ file: path.resolve("shot.png") }); Defensive patterns
Strategy: validation
Validate before calling
function assertAbsoluteOut(p) {
if (typeof p !== "string" || !path.isAbsolute(p) || p.includes("\0"))
throw new TypeError("output path must be an absolute filename");
} Type guard
const isSafeAbsPath = (p) => typeof p === "string" && path.isAbsolute(p) && !p.includes("\0"); Try / catch
try { await backend.screenshot({ file }); }
catch (e) {
if (String(e.message).includes("absolute filename")) file = path.resolve(file);
else throw e;
} Prevention
- Always path.resolve() user-supplied output filenames
- Use a fixed absolute output directory
- Reject relative paths at your app's config boundary
When it happens
Trigger: Calling a capture/recording API (e.g. `takeShot`/screenshot with `file`) with a relative path like "shot.png", an empty string, a non-string value, or a path containing "\0" (backends/linux.mjs:55).
Common situations: Passing a filename from CLI args without resolving it; assuming the process cwd applies; concatenating user input into a path.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Android reported non-absolute loaded-image path
- --app must be `web` or `headless`, got
- audited skill path does not match owned package
- bundle path escapes the config directory via a symlink…
- bundle path is absolute; only paths inside the config…
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/75a791f92356b372.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/plugins/computer-use/src/backends/linux.mjs:55
function appName(ref) {
if (ref === undefined) return "";
if (!ref || typeof ref !== "object" || Array.isArray(ref) || Object.keys(ref).length !== 1 || typeof ref.name !== "string" || !ref.name.trim()) {
throw Object.assign(new ExecError("Linux accessibility targeting supports only a nonblank app_ref.name; PID and bundle selectors are unavailable"), { code: "unsupported_selector" });
}
return ref.name;
}
function rejectWindowSelectors(args) {
if (Object.hasOwn(args, "app_ref") || Object.hasOwn(args, "window_id")) throw Object.assign(new ExecError("Linux window listing and screenshots do not support app_ref or window_id selectors"), { code: "unsupported_selector" });
}
function assertAppRootWindow(index, windowId) {
if (windowId !== undefined || (index !== undefined && index !== 0)) throw Object.assign(new ExecError("Linux accessibility paths start at the app root; window selectors are unavailable"), { code: "unsupported_selector" });
}
function outputPath(file) {
if (typeof file !== "string" || !path.isAbsolute(file) || file.includes("\0")) throw new ExecError("output path must be an absolute filename");
return file;
}
export function create({ exec } = {}) {
const run = exec?.run ?? nativeRun;
const have = exec?.have ?? nativeHave;
const browser = createBrowser({ platform: "linux" });
function requireInputOwner() {
if (exec?.persistentInputOwner !== true) throw Object.assign(new ExecError(
"This held-input gesture requires a connected Codewhale Computer Use desktop helper so a disconnected client cannot leave keys or buttons pressed. Start the helper and reconnect before retrying."
), { code: "input_owner_required" });
}
const tools = {};
let session = null; // "x11" | "wayland"
let probed = false;
let lastRaster = null;
let mouseHeld = false;View on GitHub (pinned to 73e0f67d83)