vitest-dev/vitest · error · Error

Cannot upload files outside of a test

Error message

Cannot upload files outside of a test

What it means

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.

Solutions

  1. Call userEvent.upload inside an `it(...)` callback so testPath is bound.
  2. Ensure the file runs under `pool: 'browser'` and matches the browser project's include glob.
  3. If uploading from a helper, only call it from within a running test.

Example fix

// before
import { userEvent } from 'vitest/browser'
await userEvent.upload(input, ['./avatar.png']) // top-level -> throws

// after
import { test } from 'vitest'
import { userEvent } from 'vitest/browser'
test('uploads avatar', async () => {
  await userEvent.upload(input, ['./avatar.png'])
})
Defensive patterns

Strategy: validation

Validate before calling

import { userEvent } from 'vitest/browser'

// only call inside a test:
test('upload', async () => {
  await userEvent.upload(input, ['./file.png'])
})

Type guard

function hasTestPath<T extends { testPath?: string }>(c: T): c is T & { testPath: string } {
  return !!c.testPath
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11). Data as JSON: /api/errors/3881c5a5d26a259d. Report an issue: GitHub.

Appendix: source

Thrown at packages/browser-playwright/src/commands/upload.ts:20

import type { UserEventUploadOptions } from 'vitest/browser'
import type { UserEventCommand } from './utils'
import { assertBrowserFileAccess } from '@vitest/browser'
import { resolve } from 'pathe'
import { getDescribedLocator } from './utils'

export const upload: UserEventCommand<(element: SerializedLocator, files: Array<string | {
  name: string
  mimeType: string
  base64: string
}>, options: UserEventUploadOptions) => void> = async (
  context,
  selector,
  files,
  options,
) => {
  const testPath = context.testPath
  if (!testPath) {
    throw new Error(`Cannot upload files outside of a test`)
  }
  const root = context.project.config.root

  const playwrightFiles = files.map((file) => {
    if (typeof file === 'string') {
      const filepath = resolve(root, file)
      assertBrowserFileAccess(context.project, filepath)
      return filepath
    }
    return {
      name: file.name,
      mimeType: file.mimeType,
      buffer: Buffer.from(file.base64, 'base64'),
    }
  })
  await getDescribedLocator(context, selector).setInputFiles(playwrightFiles as string[], options)
}

View on GitHub (pinned to 1fa9837ec2)