{"id":"3881c5a5d26a259d","repo":"vitest-dev/vitest","slug":"cannot-upload-files-outside-of-a-test","errorCode":null,"errorMessage":"Cannot upload files outside of a test","messagePattern":"Cannot upload files outside of a test","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/browser-playwright/src/commands/upload.ts","lineNumber":20,"sourceCode":"import type { UserEventUploadOptions } from 'vitest/browser'\nimport type { UserEventCommand } from './utils'\nimport { assertBrowserFileAccess } from '@vitest/browser'\nimport { resolve } from 'pathe'\nimport { getDescribedLocator } from './utils'\n\nexport const upload: UserEventCommand<(element: SerializedLocator, files: Array<string | {\n  name: string\n  mimeType: string\n  base64: string\n}>, options: UserEventUploadOptions) => void> = async (\n  context,\n  selector,\n  files,\n  options,\n) => {\n  const testPath = context.testPath\n  if (!testPath) {\n    throw new Error(`Cannot upload files outside of a test`)\n  }\n  const root = context.project.config.root\n\n  const playwrightFiles = files.map((file) => {\n    if (typeof file === 'string') {\n      const filepath = resolve(root, file)\n      assertBrowserFileAccess(context.project, filepath)\n      return filepath\n    }\n    return {\n      name: file.name,\n      mimeType: file.mimeType,\n      buffer: Buffer.from(file.base64, 'base64'),\n    }\n  })\n  await getDescribedLocator(context, selector).setInputFiles(playwrightFiles as string[], options)\n}\n","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/vitest-dev/vitest/blob/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/browser-playwright/src/commands/upload.ts#L2-L38","documentation":"Thrown by the Playwright upload user-event command when context.testPath is falsy. The upload command resolves file paths relative to the project root and the test file; without a bound test it refuses to read files from disk (also a safety check against arbitrary path uploads outside a test).","triggerScenarios":"Calling page.upload(element, files) from global setup, a beforeAll in a non-test module, or any context without a testPath. Also triggered by manually invoking the upload command with a hand-built context.","commonSituations":"Uploading fixtures from setup files, shared utils imported outside tests, or invoking upload inside worker-scoped hooks that lack a test path.","solutions":["Call page.upload from inside an it/test body so testPath is set.","Move file-upload logic out of global setup and into the test that triggers the upload.","For setup-time uploads, drive the <input type=file> via Playwright's setInputFiles directly with absolute paths."],"exampleFix":"// before (setup.ts)\nimport { page } from '@vitest/browser'\nawait page.upload(fileInput, ['./fixture.png'])\n\n// after (test file)\nimport { test } from 'vitest'\nimport { page } from '@vitest/browser'\ntest('upload', async () => {\n  await page.upload(fileInput, ['./fixture.png'])\n})","handlingStrategy":"validation","validationCode":"if (!context.testPath) {\n  throw new Error('upload must be called from within a test')\n}\nawait upload(context, selector, files, options)","typeGuard":"function inTestFile(c: BrowserCommandContext): c is BrowserCommandContext & { testPath: string } {\n  return typeof c.testPath === 'string' && c.testPath.length > 0\n}","tryCatchPattern":null,"preventionTips":["Call page.upload only from it/test bodies.","Keep shared helpers that use @vitest/browser upload out of node-pool tests.","For setup uploads, use Playwright setInputFiles directly with absolute paths."],"tags":["browser","upload","user-event","test-context","playwright","vitest"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}