{"record":{"id":"9eec22591b74422e","repo":"can1357/oh-my-pi","slug":"tab-uploadfile-requires-at-least-one-file-path-9eec22","errorCode":null,"errorMessage":"tab.uploadFile() requires at least one file path","messagePattern":"tab\\.uploadFile\\(\\) requires at least one file path","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/browser/tab-worker.ts","lineNumber":2068,"sourceCode":"\t\t\t\t\t}\n\t\t\t\t\tselect.dispatchEvent(new EventCtor(\"input\", { bubbles: true }));\n\t\t\t\t\tselect.dispatchEvent(new EventCtor(\"change\", { bubbles: true }));\n\t\t\t\t\treturn selected;\n\t\t\t\t}, values),\n\t\t\t)) as string[];\n\t\t} finally {\n\t\t\tawait handle.dispose().catch(() => undefined);\n\t\t}\n\t}\n\n\tasync #uploadFile(\n\t\tselector: string,\n\t\tfilePaths: string[],\n\t\ttimeoutMs: number,\n\t\tsignal: AbortSignal,\n\t\tsession: SessionSnapshot,\n\t): Promise<void> {\n\t\tif (!filePaths.length) throw new ToolError(\"tab.uploadFile() requires at least one file path\");\n\t\tconst handle = await this.#resolveActionHandle(selector, timeoutMs, signal);\n\t\ttry {\n\t\t\tconst absolute = filePaths.map(filePath => resolveToCwd(filePath, session.cwd));\n\t\t\tconst upload = handle as unknown as { uploadFile: (...paths: string[]) => Promise<void> };\n\t\t\tconst tagName = (await untilAborted(signal, () =>\n\t\t\t\thandle.evaluate(el => (el as unknown as { tagName: string }).tagName),\n\t\t\t)) as string;\n\t\t\tif (tagName !== \"INPUT\")\n\t\t\t\tthrow new ToolError(\n\t\t\t\t\t`tab.uploadFile() requires an <input type=\"file\"> element (got <${tagName.toLowerCase()}>)`,\n\t\t\t\t);\n\t\t\tawait untilAborted(signal, () => upload.uploadFile(...absolute));\n\t\t} finally {\n\t\t\tawait handle.dispose().catch(() => undefined);\n\t\t}\n\t}\n\n\tasync #waitForUrl(pattern: string | RegExp, timeout: number, signal: AbortSignal): Promise<string> {","sourceCodeStart":2050,"sourceCodeEnd":2086,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/browser/tab-worker.ts#L2050-L2086","documentation":"tab.uploadFile() validates its filePaths array before doing any work; an empty array cannot identify any file, so it throws this ToolError immediately. This is a pre-condition check guarding the subsequent uploadFile call.","triggerScenarios":"Calling tab.uploadFile(selector, []) — e.g. an upload list built from zero matched files, or a caller forwarding an optional paths array that was undefined-normalized to [].","commonSituations":"A glob/glob-like expansion produced no matches before the call; an agent omitted the files argument; config pointed at a directory with no files so the collected list was empty.","solutions":["Pass at least one existing file path in filePaths.","Check whatever produced the list (glob, readdir) and assert it is non-empty before calling.","If the upload is optional, skip the call entirely when the list is empty instead of invoking it."],"exampleFix":"// before\nconst files = fs.readdirSync(dir).filter(f => f.endsWith(\".csv\"));\nawait tab.uploadFile(\"#file\", files); // throws when dir has no .csv\n// after\nconst files = fs.readdirSync(dir).filter(f => f.endsWith(\".csv\"));\nif (files.length > 0) await tab.uploadFile(\"#file\", files.map(f => path.join(dir, f)));","handlingStrategy":"validation","validationCode":"if (!filePaths?.length) {\n  throw new Error(\"uploadFile called with no file paths; check the file list source\");\n}","typeGuard":"function hasFiles(paths: unknown): paths is [string, ...string[]] {\n  return Array.isArray(paths) && paths.length > 0 && paths.every(p => typeof p === \"string\");\n}","tryCatchPattern":"try {\n  await tab.uploadFile(selector, filePaths);\n} catch (err) {\n  if (err.message.includes(\"at least one file path\")) {\n    return skipUpload(); // upload was optional\n  }\n  throw err;\n}","preventionTips":["Guard the paths array before calling","Skip optional uploads when the list is empty","Log why the file list was empty (glob miss, bad dir) to aid debugging","Validate paths exist on disk before the call"],"tags":["browser","upload","validation","arguments"],"backgroundTag":"invalid-argument-shape","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}