`parseAsync()` can return the fastest successful union option instead of the first option in order
Author: AaroniusCreated Sep 16, 2026Updated Sep 16, 2026
When parsing a union asynchronously, an earlier option may return a promise while a later synchronous option succeeds immediately. In that case, parseAsync() returns the later option's result without waiting for the earlier option.
For example:
import * as z from "zod";
const schema = z.union([
z.string().transform(async () => {
await Promise.resolve();
return "first";
}),
z.string().transform(() => "second"),
]);
console.log(await schema.parseAsync("input"));
Actual behavior: second
Expected behavior: first
The documentation states:
The first value that validates successfully is returned.
I assume “first” means the first successful option in the order supplied to z.union(), rather than whichever option finishes first.
I have a fix here and am happy to open a PR for it (I don't have rights to do so).
Source: colinhacks/zod