「とりあえず npm install で新しい SDK に差し替えて、あとは型エラーが出る箇所だけ直せばいい」— @google/genai への移行をそんな気軽な気持ちで始めて、しっかり半日溶かした方は、私だけではないのではないでしょうか。
旧 SDK の @google/generative-ai から新 SDK の @google/genai へは、単なるリブランディングではなく、API 設計そのものが整理されています。GoogleGenerativeAI クラスがなくなり、getGenerativeModel() も廃止、generateContent の引数も変わりました。素直に置換しただけでは動かないコードが多いはずです。
ここでは私が実際に4プロジェクトを移行する過程で踏んだエラーを、原因と最短の修正パターンに整理しています。Node.js / TypeScript で本番コードを動かしている方が、移行の半日を1時間に縮められる構成にしました。
エラー1: GoogleGenerativeAI is not a constructor
旧 SDK のコードをそのままにして package.json だけ差し替えると、起動直後にこの例外で落ちます。
// ❌ 旧 SDK の書き方(@google/genai では動かない)
import { GoogleGenerativeAI } from "@google/genai";
const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY!);
const model = genAI.getGenerativeModel({ model: "gemini-2.5-pro" });新 SDK は GoogleGenAI という別クラスが入口です。Generative の単語が消え、メソッド体系もフラット化されています。
// ✅ 新 SDK の書き方
import { GoogleGenAI } from "@google/genai";
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
const response = await ai.models.generateContent({
model: "gemini-2.5-pro",
contents: "こんにちは",
});
console.log(response.text);ポイントは3つあります。コンストラクタがオブジェクト引数になったこと、getGenerativeModel() が消えて ai.models.generateContent() で直接呼ぶ形になったこと、そして response.text がプロパティになり関数呼び出し(response.text())ではないことです。最後の点は次のエラーに繋がります。
エラー2: response.text is not a function
旧 SDK では result.response.text() で本文を取得していましたが、新 SDK では response.text がただのゲッターです。
// ❌ 関数として呼ぶと TypeError
const text = response.text();
// ✅ プロパティとしてアクセスする
const text = response.text;ストリーミングも同様で、旧 SDK の result.stream ではなく generateContentStream() を別メソッドとして呼びます。
const stream = await ai.models.generateContentStream({
model: "gemini-2.5-flash",
contents: "短い詩を書いてください",
});
for await (const chunk of stream) {
process.stdout.write(chunk.text ?? "");
}chunk.text は最後のチャンクで undefined になることがあるため、必ず ?? "" でガードしてください。
エラー3: safetySettings の enum 名が違う
旧 SDK の HarmCategory.HARM_CATEGORY_HARASSMENT を新 SDK にそのまま持ち込むと、TypeScript の型エラーか、実行時に「Invalid harm category」と言われます。
新 SDK では文字列リテラルでもよく、enum を使う場合は import パスが変わります。
import { HarmCategory, HarmBlockThreshold } from "@google/genai";
const response = await ai.models.generateContent({
model: "gemini-2.5-pro",
contents: prompt,
config: {
safetySettings: [
{
category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
},
],
},
});私の経験では、移行エラーの中でもっとも見落とされやすいのが generationConfig から config へのリネームです。config の中に safetySettings・systemInstruction・responseSchema・thinkingConfig などがフラットに同居する設計に変わっています。旧 SDK の感覚で generationConfig: { ... } と書くと、設定がまるごと無視されて「temperature を下げたのに応答が変わらない」という現象になります。
エラー4: Function Calling のスキーマ型が Type enum に変わった
旧 SDK では JSON Schema をそのまま parameters に渡せましたが、新 SDK は内部で Type enum を使う構造に整理されました。
import { GoogleGenAI, Type } from "@google/genai";
const tools = [
{
functionDeclarations: [
{
name: "get_weather",
description: "指定都市の現在の天気を取得します",
parameters: {
type: Type.OBJECT,
properties: {
city: { type: Type.STRING, description: "都市名" },
unit: {
type: Type.STRING,
enum: ["celsius", "fahrenheit"],
},
},
required: ["city"],
},
},
],
},
];type: "object" のような文字列リテラルでも一応動きますが、TypeScript の型推論が効かないため Type.OBJECT を使うのが推奨です。
Function Calling が動かないときの詳しい切り分けは Gemini Function Calling のトラブルシューティング記事 にまとめていますので、合わせてご確認ください。
エラー5: Vertex AI モードの初期化引数が違う
API キー方式(Google AI Studio)と Vertex AI 方式が、新 SDK では1つのクラスで切り替えられるようになりました。これは便利な反面、初期化引数を間違えると無言で別のエンドポイントを叩きます。
// Google AI Studio(個人開発・スモールビジネス向け)
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
// Vertex AI(GCP プロジェクト・本番運用向け)
const ai = new GoogleGenAI({
vertexai: true,
project: process.env.GOOGLE_CLOUD_PROJECT,
location: "us-central1",
});Vertex AI モードでは apiKey ではなく Application Default Credentials(ADC)を読みます。ローカル環境では gcloud auth application-default login を一度通しておく必要があります。本番のクラウドランタイム(Cloud Run, Cloud Functions など)ではサービスアカウントが自動で割り当たります。
このあたりは Vertex AI 認証エラーの修正手順 で詳しく扱っていますので、ADC まわりで詰まった方はそちらをご覧ください。
エラー6: response.candidates[0].content.parts[0].text が undefined
新 SDK では text プロパティが SDK 側で組み立てられるため、複雑なレスポンス(思考プロセス込み・複数モダリティ含む)でも response.text で本文だけ取れます。逆に、旧 SDK の感覚で生の candidates を掘ろうとすると、parts の中に thought: true のセグメントが混ざっていて空文字を引いてしまうことがあります。
// ❌ 思考プロセスのパートを引いてしまう可能性がある
const text = response.candidates[0].content.parts[0].text;
// ✅ SDK が整形した text を使う
const text = response.text;
// 思考プロセスだけ取り出したい場合
const thoughts = response.candidates?.[0]?.content?.parts
?.filter((p) => (p as any).thought)
?.map((p) => p.text)
?.join("\n");Gemini 2.5 系の thinkingConfig を有効にしている方は、ここでハマりやすいので注意してください。
エラー7: Edge Runtime / Cloudflare Workers でビルドが通らない
新 SDK は Node.js 依存を整理しているとはいえ、いくつかの内部ヘルパーが node:crypto や node:stream を参照する経路が残っています。素直に Cloudflare Workers にデプロイすると、ビルド時に「Module not found: node:stream」と叱られることがあります。
回避策としては、wrangler.toml で nodejs_compat フラグを有効にするのが最短です。
compatibility_flags = ["nodejs_compat"]
compatibility_date = "2026-03-01"それでも詰まる場合は、SDK を直接呼ばず REST 互換の薄いラッパー(fetch で https://generativelanguage.googleapis.com/v1beta/models/...:generateContent を叩く実装)に差し替えることも検討してください。私はエッジ環境ではこちらに倒すことが多いです。
エッジ特有のサブリクエスト上限など、より深い問題は Gemini API の Edge Runtime サブリクエスト上限のトラブルシューティング記事 にまとめてあります。
移行を一気に進めるための小さなコツ
最後に、私が実際に移行を進めるとき意識していることを2つだけ共有させてください。1つ目は、移行前後で同じプロンプトを叩いて出力を比較するスナップショットテストを必ず1ファイル分用意することです。新 SDK は内部で system instruction の扱いが少し変わっているため、見た目には動いていても出力品質が微妙に変わるケースがあります。
2つ目は、型エラーをいったん全部 // @ts-expect-error で潰してから動かしてみることです。型と実装のどちらに問題があるのか切り分けやすくなり、結果的に最短で本質的な修正にたどり着けます。
新 SDK のインストールやバージョン固定で詰まったときは Gemini SDK バージョンインストールエラーの修正記事 も参考になるはずです。
Node.js のストリームや非同期処理の感覚を再確認しておくと、新 SDK の generateContentStream の挙動も腑に落ちやすくなります。
全体を振り返って — 移行で最初に確認したい1点
もし移行がうまくいかず時間が溶けそうであれば、まず config プロパティに safetySettings や systemInstruction をフラットに入れているかを確認してください。旧 SDK の感覚で generationConfig の中に押し込んでいる場合、ほかの設定もすべて無視されて挙動が読めなくなります。ここを直すだけで、残りのエラーがガクッと減るはずです。