Skip to content

Commit e7c9843

Browse files
Added an error message to nudge folks to the new SDK, and also updated the README.
1 parent d0c7898 commit e7c9843

File tree

2 files changed

+65
-38
lines changed

2 files changed

+65
-38
lines changed

README.md

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
# Google AI SDK for JavaScript
1+
# Google Generative AI for Node.js
22

3-
> [!NOTE] A new Javascript/Typescript SDK, `@google/genai`
4-
> ([github](https://github.com/googleapis/js-genai/tree/main)), is currently
5-
> available in a *preview launch* - designed to work with Gemini 2.0 features
6-
> and support both the Gemini API and the Vertex API.
3+
> **IMPORTANT:** This SDK is intended for use with older Gemini models (e.g., Gemini 1.0 Pro, Gemini 1.5 Pro). For access to the latest models, including Gemini 2.0 and Gemini 2.5 Pro, please use the newer SDK available at [https://github.com/googleapis/js-genai](https://github.com/googleapis/js-genai).
74
85
The Google AI JavaScript SDK is the easiest way for JavaScript developers to
96
build with the Gemini API. The Gemini API gives you access to Gemini

src/requests/request.ts

Lines changed: 63 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,28 @@ export async function getHeaders(url: RequestUrl): Promise<Headers> {
111111
return headers;
112112
}
113113

114+
/**
115+
* Generates the request options to be passed to the fetch API.
116+
* @param requestOptions - The user-defined request options.
117+
* @returns The generated request options.
118+
*/
119+
function buildFetchOptions(requestOptions?: SingleRequestOptions): RequestInit {
120+
const fetchOptions = {} as RequestInit;
121+
if (requestOptions?.signal !== undefined || requestOptions?.timeout >= 0) {
122+
const controller = new AbortController();
123+
if (requestOptions?.timeout >= 0) {
124+
setTimeout(() => controller.abort(), requestOptions.timeout);
125+
}
126+
if (requestOptions?.signal) {
127+
requestOptions.signal.addEventListener("abort", () => {
128+
controller.abort();
129+
});
130+
}
131+
fetchOptions.signal = controller.signal;
132+
}
133+
return fetchOptions;
134+
}
135+
114136
export async function constructModelRequest(
115137
model: string,
116138
task: Task,
@@ -196,46 +218,54 @@ async function handleResponseNotOk(
196218
response: Response,
197219
url: string,
198220
): Promise<void> {
199-
let message = "";
221+
let originalMessage = "";
200222
let errorDetails;
223+
let isUnsupportedModelError = false;
224+
const newSdkUrl = "https://github.com/googleapis/js-genai";
225+
// Patterns for newer models likely requiring the new SDK
226+
const unsupportedModelPatterns = [/gemini-2/, /gemini-pro-2.0/, /gemini-ultra-2.0/, /gemini-flash-2.5/, /gemini-pro-2.5/];
227+
228+
// Extract model name from the URL
229+
let requestedModel = "unknown";
230+
// Match /v.../models/model-name: or /v.../tunedModels/model-name:
231+
const modelNameMatch = url.match(/\/(v\d+(?:beta)?\d*)\/(?:models|tunedModels)\/([^:]+):/);
232+
if (modelNameMatch && modelNameMatch[2]) {
233+
requestedModel = modelNameMatch[2];
234+
}
235+
201236
try {
202237
const json = await response.json();
203-
message = json.error.message;
204-
if (json.error.details) {
205-
message += ` ${JSON.stringify(json.error.details)}`;
206-
errorDetails = json.error.details;
238+
originalMessage = json.error?.message || ""; // Safely access message
239+
errorDetails = json.error?.details; // Safely access details
240+
241+
// Check 1: Explicit model name check
242+
if (unsupportedModelPatterns.some(pattern => pattern.test(requestedModel))) {
243+
// If the requested model *is* one of the new ones, assume this error is due to SDK incompatibility.
244+
isUnsupportedModelError = true;
245+
}
246+
247+
// Append original details to message if they exist and aren't already in the message
248+
if (errorDetails && !originalMessage.includes(JSON.stringify(errorDetails))) {
249+
originalMessage += ` ${JSON.stringify(errorDetails)}`;
207250
}
251+
208252
} catch (e) {
209-
// ignored
253+
// Error parsing JSON is ignored, proceed with original status/text
254+
}
255+
256+
let finalMessage = `Error fetching from ${url.toString()}: [${response.status} ${response.statusText}] ${originalMessage || 'Server responded with an error.'}`; // Provide default if message is empty
257+
258+
if (isUnsupportedModelError) {
259+
// Prepend the specific message for known unsupported models
260+
finalMessage = `It looks like you're trying to use a newer Gemini model (${requestedModel}) with an older SDK. This model requires the latest SDK. Please upgrade to the latest SDK available at ${newSdkUrl}. Original error: ${finalMessage}`;
261+
} else if ((response.status === 400 || response.status === 404) && (originalMessage.includes("Invalid model") || originalMessage.includes("not found") || originalMessage.includes("API key not valid"))) {
262+
// Add a more general hint for other model-related or key errors that might be due to trying new models/regions
263+
finalMessage += `\nHint: If you are trying to use a newer Gemini model (e.g., Gemini 2.0, 2.5 Pro) or a specific region, ensure your API key is valid for that model/region and consider upgrading to the latest SDK: ${newSdkUrl}`;
210264
}
265+
211266
throw new GoogleGenerativeAIFetchError(
212-
`Error fetching from ${url.toString()}: [${response.status} ${
213-
response.statusText
214-
}] ${message}`,
267+
finalMessage,
215268
response.status,
216269
response.statusText,
217-
errorDetails,
218270
);
219-
}
220-
221-
/**
222-
* Generates the request options to be passed to the fetch API.
223-
* @param requestOptions - The user-defined request options.
224-
* @returns The generated request options.
225-
*/
226-
function buildFetchOptions(requestOptions?: SingleRequestOptions): RequestInit {
227-
const fetchOptions = {} as RequestInit;
228-
if (requestOptions?.signal !== undefined || requestOptions?.timeout >= 0) {
229-
const controller = new AbortController();
230-
if (requestOptions?.timeout >= 0) {
231-
setTimeout(() => controller.abort(), requestOptions.timeout);
232-
}
233-
if (requestOptions?.signal) {
234-
requestOptions.signal.addEventListener("abort", () => {
235-
controller.abort();
236-
});
237-
}
238-
fetchOptions.signal = controller.signal;
239-
}
240-
return fetchOptions;
241-
}
271+
}

0 commit comments

Comments
 (0)