GEMINI LABJP
NANOLITE — Nano Banana 2 Lite is here: Google's fastest and most cost-efficient Gemini Image model, made for running lightweight image generation cheaplyOMNIFLASH — Gemini Omni Flash is in public preview, a natively multimodal model that lets enterprises and developers build custom, dynamic video workflowsAGENTS — Managed Agents expand with background: true for async server-side runs and polling, remote MCP server integration, and refreshing credentials across interactionsMEMORY — The Memory Bank IngestEvents API is generally available, decoupling event ingestion from memory generation so you can stream content continuouslyTHROUGHPUT — Provisioned Throughput now lets you submit up to seven pending orders for the same model and regionDEPRECATE — Image generation models shut down on August 17, and the Grok 4.1 family on the Gemini Enterprise Agent Platform on August 20NANOLITE — Nano Banana 2 Lite is here: Google's fastest and most cost-efficient Gemini Image model, made for running lightweight image generation cheaplyOMNIFLASH — Gemini Omni Flash is in public preview, a natively multimodal model that lets enterprises and developers build custom, dynamic video workflowsAGENTS — Managed Agents expand with background: true for async server-side runs and polling, remote MCP server integration, and refreshing credentials across interactionsMEMORY — The Memory Bank IngestEvents API is generally available, decoupling event ingestion from memory generation so you can stream content continuouslyTHROUGHPUT — Provisioned Throughput now lets you submit up to seven pending orders for the same model and regionDEPRECATE — Image generation models shut down on August 17, and the Grok 4.1 family on the Gemini Enterprise Agent Platform on August 20
Articles/Dev Tools
Dev Tools/2026-03-21Advanced

When Gemini Nano Won't Run — Chrome and Android Have Different Doors

Pasting a Gemini Nano sample often fails. Chrome moved from the ai.* namespace to LanguageModel, and Android's entry point is ML Kit GenAI. Here is what works today, plus the device requirements nobody mentions.

Gemini Nano2On-Device AI2Chrome Built-in AIML KitAndroid10

Premium Article

If summarization ran offline, it would work in places with no signal. That was the thought behind pasting a sample into the Chrome console. What came back was a single line:

Uncaught ReferenceError: ai is not defined

I checked the spelling. I checked the flags. I restarted Chrome. It was none of those. The ai namespace itself no longer existed.

Gemini Nano is usually described as "the lightweight Gemini," but the thing that actually blocks you isn't model capability. It's which door you walked through, and whether you assumed the model was already on the device. Miss either one and your prompt never executes, no matter how well written it is.

Here's where Chrome and Android each stand today.

ai.languageModel no longer exists

Early builds of Chrome's Built-in AI hung everything off a global called ai (or window.ai). Most samples still floating around date from that period.

Today each capability lives on its own global class.

// Old: throws "ai is not defined"
const session = await ai.languageModel.create({
  systemPrompt: "You are a helpful assistant."
});
 
// Current: call the LanguageModel global directly
const session = await LanguageModel.create({
  initialPrompts: [
    { role: 'system', content: 'You are a helpful assistant. Keep answers brief.' }
  ]
});

The system prompt moved too. Instead of a dedicated systemPrompt field, you put a role: 'system' message at the head of initialPrompts. Restoring a stored conversation uses the same array with user and assistant entries, which I find more honest about what's actually happening.

Summarization changed the same way.

// Old
const summarizer = await ai.summarizer.create({ type: "tl;dr" });
 
// Current
const summarizer = await Summarizer.create({
  type: 'tldr',          // tldr / key-points / teaser / headline
  length: 'short',
  format: 'plain-text',
});

Notice type went from "tl;dr" to 'tldr'. Fix only the namespace and you'll get rejected on the option value instead — one error swapped for another.

These APIs also haven't landed as one bundle. As of July 2026 they're spread across different stages.

APIFrom a web pageFrom a Chrome extension
Translator / Language DetectorStable in Chrome 138Stable in Chrome 138
SummarizerStable in Chrome 138Stable in Chrome 138
PromptStable in Chrome 148Stable in Chrome 138
Writer / RewriterDeveloper trialDeveloper trial
ProofreaderDeveloper trialDeveloper trial

Look at the Prompt row. Extensions got it as stable in 138; ordinary web pages had to wait until 148. Ten versions apart, for the same API. That gap is exactly why code that worked in your extension can die when you move it to a page.

I'd hold off on building a core feature on Writer or Rewriter. A developer trial is something you adopt knowing the shape may change. The Built-in AI API status table is the source of truth here.

Skip availability() and create() will fail

Fix the namespace and it still might not run. This is the next place to look.

Gemini Nano does not ship inside Chrome. The API is built into the browser, but the model downloads separately the first time an origin uses it. So at the moment your code runs, the model may simply not be there.

That's why the current API is shaped around asking before acting.

// 1. Check the state
//    Pass availability() the same options you'll pass prompt()
const availability = await LanguageModel.availability({
  expectedInputs: [{ type: 'text', languages: ['en'] }],
  expectedOutputs: [{ type: 'text', languages: ['en'] }],
});
 
if (availability === 'unavailable') {
  // Device doesn't meet the requirements — route to cloud, or hide the feature
  return fallbackToCloud();
}
 
// 2. Start the download from a user gesture
//    When availability is 'downloadable', create() needs user activation
downloadButton.addEventListener('click', async () => {
  const session = await LanguageModel.create({
    monitor(m) {
      m.addEventListener('downloadprogress', (e) => {
        progressBar.value = e.loaded * 100;
      });
    },
  });
 
  // 3. Only now can you run
  const result = await session.prompt('Summarize this article in three lines.');
  console.log(result);
});

Two things get skipped here more than anything else.

First, pass identical options to availability() and prompt(). Some language and modality combinations aren't supported, and if the options drift apart you get "available" back and then a NotSupportedError at execution time.

Second, user activation. Calling create() on page load will always fail on a device without the model. That's deliberate — a multi-gigabyte download shouldn't start without consent. Your dev machine already has the model, so this passes locally and surfaces for the first time in production.

Working solo as an indie developer, I nearly signed off on code that skipped both. It "worked" only because my own Chrome already had the model cached. Since then I treat the first-run experience on a model-less device as the real test, not the happy path on my laptop.

One more detail: availability() returns one of 'unavailable', 'downloadable', 'downloading', or 'available'. It's not a boolean, so if (availability) happily lets 'unavailable' through.

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
The check to download to run pattern that actually works in current Chrome and Android
First-download and inference latency measured on one machine, next to a cloud round-trip
Exception branches that survive QuotaExceededError and model eviction, always falling back to cloud
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

Dev Tools2026-05-29
Treating a 0.5B Local LLM as a 'Front-Line Router' — Gemini Nano Next to Qwen 0.5B
Qwen2.5 0.5B reads as 'too weak for daily chat' when you give it the wrong task. As a mobile-app developer with 50M cumulative downloads behind me, I find it useful to put Gemini Nano next to Qwen 0.5B and think about the routing layer instead.
Dev Tools2026-07-18
I Was Handing Gemini Obfuscated Stack Traces — Until retrace Went In Front, the Diagnoses Were Confident and Wrong
Release stack traces come out of R8 with the names flattened. Feed one to Gemini as-is and the diagnosis arrives calm, well-written, and wrong. Put retrace in front, match the mapping by versionCode, and forbid confident answers when you cannot restore. Numbers from 42 reports.
Dev Tools2026-04-01
Gemini × Rork: Build iOS/Android Apps with AI — 2026
A practical guide to building iOS and Android apps using Gemini and Rork. Learn how to integrate the Gemini API into an AI-generated React Native project — from UI scaffolding to intelligent chat, image analysis, and beyond.
📚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 →