{"record":{"id":"05ac99c34d09cbe0","repo":"openclaw/openclaw","slug":"paths-required","errorCode":null,"errorMessage":"paths required","messagePattern":"paths required","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"extensions/browser/src/browser-tool.ts","lineNumber":937,"sourceCode":"          return {\n            content: [{ type: \"text\" as const, text: `FILE:${result.path}` }],\n            details: result,\n          };\n        }\n        case \"download\":\n        case \"waitfordownload\":\n          return await executeDownloadAction({\n            action,\n            input: params,\n            baseUrl,\n            profile,\n            proxyRequest,\n            onTabActivity: sessionTabs.touch,\n          });\n        case \"upload\": {\n          const paths = Array.isArray(params.paths) ? params.paths.map((p) => String(p)) : [];\n          if (paths.length === 0) {\n            throw new Error(\"paths required\");\n          }\n          const resolvedResult = await resolveExistingUploadPaths({ requestedPaths: paths });\n          if (!resolvedResult.ok) {\n            throw new Error(resolvedResult.error);\n          }\n          const normalizedPaths = resolvedResult.paths;\n          const ref = readStringParam(params, \"ref\");\n          const inputRef = readStringParam(params, \"inputRef\");\n          const element = readStringParam(params, \"element\");\n          const { targetId, timeoutMs } = readOptionalTargetAndTimeout(params);\n          const request = {\n            paths: normalizedPaths,\n            ref,\n            inputRef,\n            element,\n            targetId,\n            timeoutMs,\n          };","sourceCodeStart":919,"sourceCodeEnd":955,"githubUrl":"https://github.com/openclaw/openclaw/blob/01804a75319da4b69c9ab98ceaa30477e22b8c0b/extensions/browser/src/browser-tool.ts#L919-L955","documentation":"Thrown by the upload action case when the 'paths' parameter is missing or resolves to an empty array after coercion. The upload action triggers a browser file-chooser dialog and needs at least one file path to upload, so an empty list is rejected before resolveExistingUploadPaths is called (browser-tool.ts:934-938).","triggerScenarios":"Calling the browser tool with {\"action\":\"upload\"} and no paths key, or {\"action\":\"upload\",\"paths\":[]}, or {\"action\":\"upload\",\"paths\":\"single-file\"} (a string, not an array, yields an empty array after the Array.isArray check).","commonSituations":"A model omitting paths because it expects the file chooser to use a clipboard or default. Passing a single path as a string instead of a one-element array. A script that dynamically builds paths and produces an empty array on a filter miss.","solutions":["Pass paths as a non-empty array: {\"action\":\"upload\",\"paths\":[\"/abs/path/to/file.pdf\"]}.","If paths come from a variable, validate it is a non-empty array before invoking the tool.","Ensure each path is a string; the code does String(p) on each element (browser-tool.ts:935)."],"exampleFix":"// before\n{ \"action\": \"upload\", \"paths\": [], \"ref\": \"fileInput\" }\n// after\n{ \"action\": \"upload\", \"paths\": [\"/tmp/report.pdf\"], \"ref\": \"fileInput\" }","handlingStrategy":"validation","validationCode":"// Validate upload paths before calling the browser tool\nfunction validateUploadArgs(paths) {\n  if (!Array.isArray(paths) || paths.length === 0) {\n    throw new Error(\"upload requires a non-empty paths array of strings\");\n  }\n  return paths.map(String);\n}","typeGuard":"function isNonEmptyStringArray(value: unknown): value is string[] {\n  return Array.isArray(value) && value.length > 0 && value.every((v) => typeof v === \"string\");\n}","tryCatchPattern":null,"preventionTips":["Always pass paths as an array, even for a single file.","Verify file existence before adding to paths.","Guard scripts to skip upload when the file list is empty."],"tags":["browser-tool","parameter-validation","upload"],"backgroundTag":null,"analyzedSha":"01804a75319da4b69c9ab98ceaa30477e22b8c0b","analyzedAt":"2026-08-12T04:37:58.197Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}