can1357/oh-my-pi · error · ToolError
tab.uploadFile() requires at least one file path
Error message
tab.uploadFile() requires at least one file path
What it means
CmuxTab.uploadFile(selector, ...filePaths) is a variadic API that base64-encodes each path and ships the payloads to the cmux daemon. It throws this ToolError synchronously when zero file paths are supplied, because the underlying browser.uploadFile request would have nothing to set.
Source
Thrown at packages/coding-agent/src/tools/browser/cmux/cmux-tab.ts:716
const dispatch = (type, point) => target.dispatchEvent(new MouseEvent(type, {
bubbles: true,
cancelable: true,
view: window,
clientX: point.x,
clientY: point.y,
buttons: type === "mouseup" ? 0 : 1,
}));
dispatch("mousemove", points.start);
dispatch("mousedown", points.start);
dispatch("mousemove", points.end);
dispatch("mouseup", points.end);
return true;
})()`,
);
}
async uploadFile(selector: string, ...filePaths: string[]): Promise<void> {
if (!filePaths.length) throw new ToolError("tab.uploadFile() requires at least one file path");
const files: FilePayload[] = [];
for (const filePath of filePaths) {
const absolute = resolveToCwd(filePath, this.#requireRunContext("tab.uploadFile()").session.cwd);
const file = Bun.file(absolute);
const data = Buffer.from(await file.arrayBuffer()).toString("base64");
files.push({ name: path.basename(absolute), type: file.type || "application/octet-stream", data });
}
await this.#selectorAction(selector, "uploadFile", { files });
}
async waitForResponse(
pattern: string | RegExp | ((response: CmuxResponse) => boolean | Promise<boolean>),
opts?: { timeout?: number },
): Promise<CmuxResponse> {
const timeoutMs = opts?.timeout ?? this.#runContext?.timeoutMs ?? 30_000;
const signal = this.#runContext?.signal;
await this.#installResponseObserver();
const startId = await this.#responseCursor();View on GitHub (pinned to 9690622007)
Solutions
- Pass at least one file path: tab.uploadFile(selector, "/path/to/file.png").
- Guard the call site: check files.length > 0 before invoking uploadFile.
- If zero files is a legitimate state, skip the upload (or clear the input with tab.evaluate) instead of calling uploadFile.
- Verify the file-collection step actually produced paths (log/validate the array before spreading).
Example fix
// before: spreads possibly-empty array
await tab.uploadFile("#avatar", ...filePaths);
// after: guard the empty case
if (filePaths.length === 0) throw new Error("no files to upload");
await tab.uploadFile("#avatar", ...filePaths); Defensive patterns
Strategy: validation
Validate before calling
if (!Array.isArray(filePaths) || filePaths.length === 0) {
throw new Error("uploadFile needs at least one file path");
} Type guard
function hasFiles(paths: unknown): paths is [string, ...string[]] {
return Array.isArray(paths) && paths.length > 0 && typeof paths[0] === "string";
} Prevention
- Validate file lists at the source before spreading into variadic calls
- Give uploadFile parameters a non-empty tuple type [string, ...string[]]
- Skip or clear the file input explicitly when zero files is a valid state
- Avoid passing optional/possibly-undefined path arrays straight into the call
When it happens
Trigger: Calling tab.uploadFile('#input') with no path arguments — typically when the caller's file list came from an empty array spread (tab.uploadFile(selector, ...files)) or from a variable that was undefined/empty.
Common situations: Spreading a dynamically collected file list that the collection step failed to populate; tool/agent code passing an optional files parameter straight through; refactoring from a single-path signature to variadic and dropping the argument.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- unknown file type: {value}
- invalid size: {value}
- 2
- invalid --block-size argument '{0}'
- invalid --time-style argument {} Possible values are: - [p
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/7c1c47b771bf85c5.
Report an issue: GitHub.