vitest-dev/vitest · error · SyntaxError
"postMessage" requires at least one argument.
Error message
"postMessage" requires at least one argument.
What it means
Inside the worker context, self.postMessage bridges messages from the worker to the main thread. Vitest reimplements it (worker.ts:74-88) and, matching browser semantics, throws a SyntaxError if it is invoked with no arguments, so code never silently sends undefined.
Solutions
- Always pass an explicit payload, e.g. self.postMessage({}) or self.postMessage(null).
- If you spread arguments, guard the array length first or pass a default: self.postMessage(payload ?? {}).
- Add a runtime guard before the call if the payload is optional.
Example fix
// before (inside worker)
self.postMessage()
// after
self.postMessage({ type: 'ready' }) Defensive patterns
Strategy: validation
Validate before calling
function postFromWorker(data) {
if (arguments.length === 0) {
throw new SyntaxError('"postMessage" requires at least one argument.')
}
self.postMessage(data)
}
// always route worker->main calls through this helper Type guard
type PostMessagePayload = unknown
function hasPayload(args: IArguments | unknown[]): args is [PostMessagePayload, ...unknown[]] {
return Array.from(args).length > 0
} Try / catch
try {
self.postMessage(payload)
} catch (e) {
if (e instanceof SyntaxError && /postMessage/.test(e.message)) {
console.warn('postMessage called with no payload; sending empty object')
self.postMessage({})
} else {
throw e
}
} Prevention
- Always pass an explicit payload, even if it is {} or null.
- Avoid spreading variable-length arrays into postMessage without a length check.
- Enable strict TypeScript so the postMessage signature flags missing arguments.
- Add a lint rule that bans a zero-argument postMessage() call.
When it happens
Trigger: Inside a @vitest/web-worker worker, calling postMessage() or self.postMessage() with zero arguments. The guard at worker.ts:75-79 fires before any message is constructed or dispatched.
Common situations: A payload that is conditionally computed and ends up undefined; spreading an array that may be empty, e.g. postMessage(...args); refactored code that dropped the argument; ported browser code relying on postMessage() as a tick signal.
Related errors
- All browser instances within a project must use the same…
- `bench.compare()` expects every argument to be the return…
- `bench.compare()` requires at least 2 benchmarks, received
- `bench()` expects a benchmark function. Call `bench(name…
- `bench.from()` expects a string path or a function…
AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11).
Data as JSON: /api/errors/0e27a57b5c4686a4.
Report an issue: GitHub.
Appendix: source
Thrown at packages/web-worker/src/worker.ts:76
origin: typeof location !== 'undefined' ? location.origin : 'http://localhost:3000',
crossOriginIsolated: false,
name: options?.name || '',
close: () => this.terminate(),
dispatchEvent: (event: Event) => {
return this._vw_workerTarget.dispatchEvent(event)
},
addEventListener: (...args: any[]) => {
if (args[1]) {
this._vw_insideListeners.set(args[0], args[1])
}
return this._vw_workerTarget.addEventListener(...args as [any, any])
},
removeEventListener: (...args: any[]) => {
return this._vw_workerTarget.removeEventListener(...args as [any, any])
},
postMessage: (...args: any[]) => {
if (!args.length) {
throw new SyntaxError(
'"postMessage" requires at least one argument.',
)
}
debug(
'posting message %o from the worker %s to the main thread',
args[0],
this._vw_name,
)
const event = createMessageEvent(args[0], args[1], cloneType())
this.dispatchEvent(event)
},
get self() {
return selfProxy
},
}
selfProxy = new Proxy(context, {View on GitHub (pinned to 1fa9837ec2)