vitest-dev/vitest · error · Error
`resolveOptions` has to be used in a test file
Error message
`resolveOptions` has to be used in a test file
What it means
resolveOptions in screenshotMatcher/utils.ts reads project-level defaults and merges them with per-call options, but it can only do that when it knows which test file is running. It throws when context.testPath is undefined, i.e. when the screenshot matcher resolution logic is invoked outside a test-file execution context where the testPath has not been threaded through.
Solutions
- Move the screenshot-matcher call inside an actual `it`/`test` body so the runner populates testPath on the command context.
- If invoking the command programmatically, construct the BrowserCommandContext with a valid testPath referring to an existing test file.
- Avoid calling screenshot-matcher utilities from setup files or hooks that run before a test file context exists.
Example fix
// before - called from a setup file, no test context
resolveOptions({ context, name, options, testName })
// after - only call inside a test
import { test } from 'vitest'
test('visual', async () => {
await expect(page).toMatchScreenshot('home.png')
}) Defensive patterns
Strategy: validation
Validate before calling
function hasTestPath(ctx: { testPath?: string }): ctx is { testPath: string } {
return typeof ctx.testPath === 'string' && ctx.testPath.length > 0
} Type guard
function isTestFileContext(ctx: unknown): ctx is { testPath: string } {
return !!ctx && typeof ctx === 'object' && typeof (ctx as any).testPath === 'string'
} Prevention
- Only call screenshot-matcher utilities from inside an `it`/`test` body.
- When constructing a BrowserCommandContext programmatically, always pass a testPath.
- Do not invoke matcher commands from setup files that run outside a test file scope.
When it happens
Trigger: Calling resolveOptions (directly or via a screenshot-matcher command) from a setup file, a global setup hook, or a custom command registered without a BrowserCommandContext that carries testPath. Also reproducible if the command is triggered from a session that is not tied to a specific test file.
Common situations: Using toMatchScreenshot inside beforeEach/beforeAll at the top level of a non-test module; invoking the screenshot matcher from a manual RPC call in a custom integration; a plugin that re-enters the matcher before the runner has assigned a testPath.
Related errors
- Cannot compare screenshots without a test path
- Invalid command name
- Invalid command name
- 'toMatchScreenshot' cannot be used without test context
- Unrecognized comparator
AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11).
Data as JSON: /api/errors/b9216eb152ba115d.
Report an issue: GitHub.
Appendix: source
Thrown at packages/browser/src/node/commands/screenshotMatcher/utils.ts:102
}
}
}
export function resolveOptions(
{
context,
name,
options,
testName,
}: {
context: BrowserCommandContext
name: string
testName: string
options: ScreenshotMatcherOptions
},
): ResolvedOptions {
if (context.testPath === undefined) {
throw new Error('`resolveOptions` has to be used in a test file')
}
const resolvedOptions = deepMerge<GlobalOptions>(
Object.create(null),
defaultOptions,
context.project.config.browser.expect?.toMatchScreenshot ?? {},
options,
)
const extensionFromName = extname(name)
// technically the type is a lie, but we check beneath and reassign otherwise
let extension = extensionFromName.replace(/^\./, '') as SupportedCodecs
// when `type` will be supported in `screenshotOptions`:
// - `'png'` should end up in `defaultOptions.screenshotOptions.type`
// - this condition should be switched around
// - the assignment should be `resolvedOptions.screenshotOptions.type = extension`View on GitHub (pinned to 1fa9837ec2)