← All free LLM API errors

Google Gemini API · checked October 10, 2026

Gemini "API key not valid. Please pass a valid API key."

"API key not valid" (400 INVALID_ARGUMENT, reason API_KEY_INVALID) means Google did not accept the key it received. Most often the key is mistyped, padded with whitespace or not loaded from the environment. Since mid-2026 two newer causes are common: AI Studio's AQ. auth keys used with old clients, and unrestricted keys that Google now rejects.

The exact error

What you see.

The first body comes from the native endpoint. The OpenAI-compatible endpoint answered a fake key with the shorter second form in June 2026.

{"error": {"code": 400, "message": "API key not valid. Please pass a valid API key.", "status": "INVALID_ARGUMENT",
  "details": [{"@type": "type.googleapis.com/google.rpc.ErrorInfo", "reason": "API_KEY_INVALID", "domain": "googleapis.com",
               "metadata": {"service": "generativelanguage.googleapis.com"}}]}}
{"error":{"code":400,"message":"Please pass a valid API key","status":"INVALID_ARGUMENT"}}

Causes

Why it happens.

  1. 1

    The key is wrong or never arrived

    A truncated copy, a trailing newline or space, quotes included in a .env file, or an environment variable that is not loaded in the process that makes the call.

  2. 2

    A new AQ. auth key in an old client

    Since May 28, 2026 AI Studio creates keys that start with AQ. instead of AIza. The deprecated @google/generative-ai SDK answers them with 401 ACCESS_TOKEN_TYPE_UNSUPPORTED, some proxies mangle them, and the OpenAI endpoint has answered "Invalid Auth key." in some reports.

  3. 3

    An unrestricted key

    Google rejects standard keys that are not restricted to the Gemini API and has blocked dormant unrestricted keys since May 7, 2026. Restrict the key to the Gemini API in AI Studio.

  4. 4

    A leaked or revoked key

    Keys found in public code are revoked; the API then answers 403 "Your API key was reported as leaked. Please use another API key."

  5. 5

    Project or key restrictions

    A key whose project has the API disabled, or that carries an HTTP-referrer restriction, fails with a 403 that names the restriction.

Fixes

How to fix it.

Check what your process actually sends

Print the length and prefix, never the whole key.

import os
k = os.environ.get("GEMINI_API_KEY", "")
print(len(k), repr(k[:4]), k != k.strip())   # e.g. 39 'AIza' False, or 'AQ.A' for new keys

Send the key once

Use the x-goog-api-key header on the native API, or Authorization: Bearer on the OpenAI-compatible endpoint. Sending both produces a "multiple authentication credentials" error.

Update old SDKs

Move from the deprecated @google/generative-ai package to @google/genai, which accepts the new AQ. keys.

Restrict or replace the key

In AI Studio, restrict the key to the Gemini API, or create a new one at aistudio.google.com/apikey.

With freelm

Handle it automatically.

freelm classifies this message, the newer "Invalid Auth key." and ACCESS_TOKEN_TYPE_UNSUPPORTED as a dead key: it disables that key for the process, continues the call on your other keys and providers, and freelm doctor prints the failure with a link to create a new key. freelm sends each key once, as a Bearer token.

freelm doctor
#  google   AIzaSy...x9yz   FAIL  key rejected (400): API key not valid. Please pass a valid API key.
#           get a new free key: https://aistudio.google.com/apikey

freelm is an open-source Python and Node.js library that pools the free tiers of Gemini, Groq, OpenRouter, Cloudflare Workers AI, Mistral, NVIDIA NIM, Z.ai and Cohere behind one OpenAI-compatible call. See how its failover works.

Questions

Related questions.

What is a Gemini AQ. key?

Since May 28, 2026 Google AI Studio creates auth keys that start with AQ. instead of AIza. Current SDKs accept them; the deprecated @google/generative-ai SDK does not.

Why do I get 403 instead of 400?

A 403 names a different problem: a leaked key, the API disabled on the key's project, or a referrer restriction. A request with no key at all also returns 403 PERMISSION_DENIED rather than this 400.