mastra-ai/mastra · error
Union must have at least 2 options
Error message
Union must have at least 2 options
What it means
defaultZodUnionHandler in schema-compatibility-v3 rebuilds Zod unions after processing each option, then asserts at least 2 options exist since z.union() requires a tuple of 2+. This guard fires when the processed union somehow ended up with fewer than 2 options.
Source
Thrown at packages/schema-compat/src/schema-compatibility-v3.ts:438
}
const description = this.mergeParameterDescription(value.description, constraints);
if (description) {
result = result.describe(description);
}
return result;
}
/**
* Default handler for Zod union types. Processes all union options.
*
* @param value - The Zod union to process
* @returns The processed Zod union
* @throws Error if union has fewer than 2 options
*/
public defaultZodUnionHandler(value: ZodUnion<[ZodTypeAny, ...ZodTypeAny[]]>): ZodTypeAny {
const processedOptions = value._def.options.map((option: ZodTypeAny) => this.processZodType(option));
if (processedOptions.length < 2) throw new Error('Union must have at least 2 options');
let result = z.union(processedOptions as [ZodTypeAny, ZodTypeAny, ...ZodTypeAny[]]);
if (value.description) {
result = result.describe(value.description);
}
return result;
}
/**
* Default handler for Zod string types. Processes string validation constraints.
*
* @param value - The Zod string to process
* @param handleChecks - String constraints to convert to descriptions vs keep as validation
* @returns The processed Zod string
*/
public defaultZodStringHandler(
value: ZodString,
handleChecks: readonly StringCheckType[] = ALL_STRING_CHECKS,
): ZodString {View on GitHub (pinned to 75dd419e61)
Solutions
- Ensure the union has at least two distinct options, e.g. z.union([z.string(), z.number()]).
- If only one option remains, use that option directly instead of wrapping it in z.union().
- If options are built at runtime, filter/branch so single-option arrays become the plain type.
- Verify you are not mis-tagging a non-union type as a union before the handler.
Example fix
// before const schema = z.union([z.string()]); // after const schema = z.string(); // or add a second option to the union
Defensive patterns
Strategy: validation
Validate before calling
function toUnionOrSingle(types: z.ZodTypeAny[]): z.ZodTypeAny {
if (types.length === 0) throw new TypeError('Need at least one type');
return types.length === 1 ? types[0] : z.union(types as [z.ZodTypeAny, z.ZodTypeAny, ...z.ZodTypeAny[]]);
} Type guard
function isValidUnion(u: z.ZodUnion<[z.ZodTypeAny, ...z.ZodTypeAny[]]>): boolean {
return u._def.options.length >= 2;
} Try / catch
try {
processed = compat.process(schema);
} catch (e) {
if (e.message === 'Union must have at least 2 options') {
throw new Error('Schema builds a union with <2 options; unwrap single-option unions', { cause: e });
}
throw e;
} Prevention
- Never construct z.union from arrays without checking length >= 2.
- Use the bare type for single-branch cases; use optional/nullable for optionality.
- Assert union arity in generated-schema tests.
When it happens
Trigger: Passing a union with fewer than two options into the compatibility layer — typically a TypeScript edge case where a union type collapsed to a single member, or building a union dynamically at runtime from an array that yielded one option.
Common situations: Runtime-constructed schemas where `options.length === 1` (should have been the bare type, not a union); refactors that removed a union member; wrapped/generated schemas mis-typed as ZodUnion.
Related errors
- Schema validation failed due to an invalid schema definition
- SchemaValidationError(field, this.formatErrors(result.error)
- We could not convert the schema to a JSONSchema
- WORKFLOW_SCHEMA_VALIDATION_FAILED
- ${this.model.modelId} does not support zod type: ${value._de
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/8f7df45f64204178.
Report an issue: GitHub.