{"record":{"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/1fa9837ec26533512fdcad8baebf249771bd340a/packages/browser-playwright/src/commands/upload.ts#L2-L38","documentation":"userEvent.upload() resolves relative file paths against the project root (context.project.config.root) and validates browser file access. To do that it needs testPath to bind the action to a test. Without testPath the command refuses — uploads must happen inside a test.","triggerScenarios":"Calling `await userEvent.upload(input, ['./file.png'])` outside an `it`/`test` body (module top-level, beforeAll without context, from a plain script, or under a pool that does not set testPath).","commonSituations":"Upload helper invoked from a non-browser pool; calling upload from a setup file that is not a test; misconfigured project where browser specs run under forks/threads.","solutions":["Call userEvent.upload inside an `it(...)` callback so testPath is bound.","Ensure the file runs under `pool: 'browser'` and matches the browser project's include glob.","If uploading from a helper, only call it from within a running test."],"exampleFix":"// before\nimport { userEvent } from 'vitest/browser'\nawait userEvent.upload(input, ['./avatar.png']) // top-level -> throws\n\n// after\nimport { test } from 'vitest'\nimport { userEvent } from 'vitest/browser'\ntest('uploads avatar', async () => {\n  await userEvent.upload(input, ['./avatar.png'])\n})","handlingStrategy":"validation","validationCode":"import { userEvent } from 'vitest/browser'\n\n// only call inside a test:\ntest('upload', async () => {\n  await userEvent.upload(input, ['./file.png'])\n})","typeGuard":"function hasTestPath<T extends { testPath?: string }>(c: T): c is T & { testPath: string } {\n  return !!c.testPath\n}","tryCatchPattern":null,"preventionTips":["Call userEvent.upload only inside an it/test body.","Keep browser specs in a dedicated project with pool: 'browser'.","Do not invoke upload from module top-level or non-test setup files."],"tags":["browser","user-event","upload","lifecycle"],"backgroundTag":null,"analyzedSha":"1fa9837ec26533512fdcad8baebf249771bd340a","analyzedAt":"2026-08-11T16:11:39.638Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}