GEMINI LABJP
FLASH GA — Gemini 3.5 Flash is now generally available, billed as the most intelligent model for sustained frontier performance on agentic and coding tasksTOGGLE — From Jun 16 the Gemini 3.5 Flash feature toggle is removed in the Global, US, and EU multi-regions, so check any configs that depend on itAGENTS — Managed Agents launched in public preview, letting developers build and deploy autonomous, stateful agents inside Google-hosted isolated Linux sandboxesIMAGE — The image preview models gemini-3.1-flash-image-preview and gemini-3-pro-image-preview shut down Jun 25; migrate to their successorsSEARCH — File Search now supports multimodal search, natively embedding and searching images via the gemini-embedding-2 modelCLI — Gemini CLI and Code Assist end individual access on Jun 18; free users and AI Pro/Ultra subscribers are directed to the Antigravity CLIFLASH GA — Gemini 3.5 Flash is now generally available, billed as the most intelligent model for sustained frontier performance on agentic and coding tasksTOGGLE — From Jun 16 the Gemini 3.5 Flash feature toggle is removed in the Global, US, and EU multi-regions, so check any configs that depend on itAGENTS — Managed Agents launched in public preview, letting developers build and deploy autonomous, stateful agents inside Google-hosted isolated Linux sandboxesIMAGE — The image preview models gemini-3.1-flash-image-preview and gemini-3-pro-image-preview shut down Jun 25; migrate to their successorsSEARCH — File Search now supports multimodal search, natively embedding and searching images via the gemini-embedding-2 modelCLI — Gemini CLI and Code Assist end individual access on Jun 18; free users and AI Pro/Ultra subscribers are directed to the Antigravity CLI
Articles/Advanced
Advanced/2026-06-14Advanced

Trusting Gemini Structured Output in Production — Schema Design, Double Validation, and Bounded Retries

Gemini's structured output guarantees parseable JSON, not correct values. Notes on schema design with @google/genai, why propertyOrdering matters, a Zod double-validation layer, handling MAX_TOKENS truncation, and a bounded-retry extraction pipeline.

gemini76structured-output15json-schemazod3production106

Premium Article

While running an invoice-sorting job, I noticed that a few records each month had a total that didn't match the sum of their line items. The JSON parsed fine. The schema validation was green. And yet the values were wrong.

This is where a lot of people stumble when they put structured output into production. Add responseMimeType: "application/json" and you really do get parseable JSON every time. But "parseable" and "correct for the business" are two different things. If you don't draw that line up front, quietly broken data flows downstream.

What follows is the order in which things actually mattered for me in production: current schema design with @google/genai, a two-layer validation approach, how to tell failures apart, and how to recover them. As of June 2026 the default model has moved up to Gemini 3.5 Flash and Structured Outputs is GA. With the behavior settling down, now feels like a good moment to firm up the design.

Why "structured output equals safe" doesn't hold

Structured output reliably guarantees roughly three things: the output follows the JSON types you specified, required fields are never missing, and values stay within the range you listed in enum. That's a big step up from the days of peeling JSON out of free-form text with regular expressions.

It just as clearly does not guarantee others: whether a number makes business sense (does the line-item sum match the grand total?), whether a date is real (will 2026-02-30 be rejected?), or cross-field consistency (if paymentStatus is paid, is paidDate actually present?). All of those live outside the schema.

In other words, structured output is the layer that guarantees shape, not the layer that guarantees meaning. In a production pipeline, keeping these as two separate pieces of code is, in my experience running this as an indie developer over the past few months, what ends up breaking least.

Schema design — teaching the model the shape

Here's the minimal setup with the current SDK. Moving from the old @google/generative-ai to @google/genai, calls consolidate into ai.models.generateContent, and configuration goes inside config.

// structured-review.ts
import { GoogleGenAI, Type } from "@google/genai";
 
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
 
// description acts as an instruction to the model. Write what goes in, not just the type
const reviewSchema = {
  type: Type.OBJECT,
  properties: {
    productName: { type: Type.STRING, description: "Name of the reviewed product" },
    rating: {
      type: Type.INTEGER,
      description: "Integer 1-5. Do not allow decimals or out-of-range values",
    },
    pros: {
      type: Type.ARRAY,
      items: { type: Type.STRING },
      description: "Positives. Only items grounded in the text",
    },
    cons: {
      type: Type.ARRAY,
      items: { type: Type.STRING },
      description: "Negatives. Only items grounded in the text",
    },
    sentiment: {
      type: Type.STRING,
      enum: ["positive", "neutral", "negative"],
      description: "Overall tone",
    },
  },
  // propertyOrdering pins the order the model generates fields in
  propertyOrdering: ["productName", "rating", "pros", "cons", "sentiment"],
  required: ["productName", "rating", "sentiment"],
};
 
export async function analyzeReview(reviewText: string) {
  const res = await ai.models.generateContent({
    model: "gemini-3.5-flash",
    contents: `Analyze the following review:\n\n${reviewText}`,
    config: {
      responseMimeType: "application/json",
      responseSchema: reviewSchema,
    },
  });
  return JSON.parse(res.text);
}

Three quiet things matter here.

description is not decoration; it's read as a real instruction. Adding "do not allow decimals or out-of-range values" rather than just "integer 1-5" visibly reduced misbehavior at the boundaries. Think of it as the place to write your floor rules, not type documentation, and quality goes up.

propertyOrdering is easy to overlook, but fixing the generation order improves stability. The model uses earlier fields as context for later ones, so putting rating before pros/cons makes the score and its reasons less likely to disagree. Conversely, putting an important judgment field last lets it get dragged around by the verbose arrays in front of it.

required stays minimal. Make everything required and the model will fabricate values for fields it can't fill. Letting the schema say "omit if absent" actually cuts down hallucination.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
A two-layer design that separates what responseSchema guarantees from business-consistency checks, with concrete code
How to use propertyOrdering, enum, and description to raise the model's output quality
Telling truncated and empty responses apart by finish_reason, and recovering them with bounded retries
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Gemini Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

Related Articles

Advanced2026-06-13
Gemini's GA Image Models Won't Output Exact Device Resolutions — A Wallpaper Pipeline That Fixes Aspect Ratio and Safe Areas
After switching to the GA image models, your wallpapers no longer fit the screen. Here's how to crop one master image into every device resolution and cut your generation count to a fraction, with full Pillow code.
Advanced2026-04-27
Self-Healing Architecture for Gemini Computer Use — Production Patterns That Keep Browser Automation Alive Beyond Day Three
Gemini Computer Use looks magical in demos but breaks daily in production: vanishing elements, surprise modals, network jitter, off-by-four-pixel clicks. This guide builds a five-layer self-healing architecture in Python that classifies failures and recovers them automatically, with working code you can drop into your agent loop today.
Advanced2026-04-25
Building Self-Critiquing Agents with Gemini API: A Production-Ready Guide to Reflection and Critic-Refiner Patterns
A production-grade walkthrough of Reflection and Critic-Refiner patterns with Gemini 3 Pro and 2.5 Flash. Covers implementation, cost guards, over-correction defenses, and monitoring signals from real deployments.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →