mastra-ai/mastra · error

Cannot flatten intersections with overlapping keys

Error message

Cannot flatten intersections with overlapping keys

What it means

defaultZodIntersectionHandler flattens z.intersection of two ZodObjects into a single object with a merged shape when all processed members are objects. Because a true intersection can allow conflicting field types, this library refuses to merge when the same key appears in both sides, throwing instead of silently picking one type.

Source

Thrown at packages/schema-compat/src/schema-compatibility-v4.ts:730

    }
    return [value];
  }

  /**
   * Default handler for Zod intersection types.
   * Flattens the intersection tree and merges object shapes into a single z.object().
   * Falls back to z.any() for non-object intersections.
   */
  public defaultZodIntersectionHandler(value: ZodIntersection<any, any>): ZodType {
    const leaves = this.collectIntersectionLeaves(value);
    const processed = leaves.map(leaf => this.processZodType(leaf));

    if (processed.every(p => p instanceof ZodObject)) {
      const mergedShape: Record<string, ZodType> = {};
      for (const obj of processed as ZodObject<any, any>[]) {
        for (const [key, field] of Object.entries(obj.shape)) {
          if (key in mergedShape) {
            throw new Error('Cannot flatten intersections with overlapping keys');
          }
          mergedShape[key] = field as ZodType;
        }
      }
      let result: ZodType = z.object(mergedShape);
      if (value.description) {
        result = result.describe(value.description);
      }
      return result;
    }

    return z.any().describe(value.description || 'intersection type');
  }

  /**
   * Processes a Zod object schema and converts it to an AI SDK Schema.
   *
   * @param zodSchema - The Zod object schema to process

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Rename the overlapping key on one side so the shapes are disjoint.
  2. Use z.object({ ...a.shape, ...b.shape }) manually with an explicit resolution for the shared key (e.g. omit it from one side via .omit()).
  3. Replace z.intersection with a single schema containing all required fields.
  4. Use z.union of the two objects if the value is really one shape OR the other, not both.

Example fix

// before
const schema = z.intersection(z.object({ id: z.string() }), z.object({ id: z.number() }));
// after
const schema = z.object({ id: z.string() }).extend({ score: z.number() });
Defensive patterns

Strategy: validation

Validate before calling

function assertDisjointShapes(a: z.ZodObject<any>, b: z.ZodObject<any>) {
  const overlap = Object.keys(a.shape).filter(k => k in b.shape);
  if (overlap.length) throw new TypeError(`Intersection keys overlap: ${overlap.join(', ')}`);
}

Try / catch

try {
  processed = compat.process(schema);
} catch (e) {
  if ((e as Error).message.includes('overlapping keys')) {
    throw new Error('Restructure: use object merge with explicit key resolution instead of z.intersection', { cause: e });
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling the Zod v4 schema compatibility layer with `z.intersection(z.object({ id: z.string() }), z.object({ id: z.number(), ... }))` or any two object schemas sharing at least one key.

Common situations: Combining base schemas with extension schemas (e.g. base + mixins) that both define `id`, `metadata`, or timestamps; spreading a common schema into domain schemas and then intersecting them; migrations from deepPartial/merge patterns.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/8a5a9bdd6672a2f4. Report an issue: GitHub.