0
# Error Handling
1
2
Exception hierarchy and error handling patterns for the Google GenAI SDK. All exceptions are unchecked (extend RuntimeException).
3
4
## Core Imports
5
6
```java
7
import com.google.genai.errors.ApiException;
8
import com.google.genai.errors.ClientException;
9
import com.google.genai.errors.ServerException;
10
import com.google.genai.errors.GenAiIOException;
11
```
12
13
## Exception Hierarchy
14
15
```
16
RuntimeException
17
├── ApiException (base for API errors)
18
│ ├── ClientException (4xx errors)
19
│ └── ServerException (5xx errors)
20
└── GenAiIOException (I/O and SDK errors)
21
```
22
23
## ApiException
24
25
Base class for all API-related errors.
26
27
```java { .api }
28
package com.google.genai.errors;
29
30
public class ApiException extends RuntimeException {
31
public ApiException(int code, String status, String message);
32
33
public int code();
34
public String status();
35
public String message();
36
37
public static void throwFromResponse(Response response);
38
}
39
```
40
41
**Usage:**
42
43
```java
44
try {
45
GenerateContentResponse response = client.models.generateContent(
46
"gemini-2.0-flash", "Hello", null);
47
} catch (ApiException e) {
48
System.err.println("API Error " + e.code() + ": " + e.message());
49
System.err.println("Status: " + e.status());
50
}
51
```
52
53
## ClientException
54
55
Client-side errors (HTTP 4xx status codes). Indicates issues with the request such as invalid parameters, authentication failures, or rate limiting.
56
57
```java { .api }
58
package com.google.genai.errors;
59
60
public final class ClientException extends ApiException {
61
public ClientException(int code, String status, String message);
62
}
63
```
64
65
**Common Status Codes:**
66
- 400 - Bad Request (invalid parameters)
67
- 401 - Unauthorized (invalid API key)
68
- 403 - Forbidden (insufficient permissions)
69
- 404 - Not Found (resource doesn't exist)
70
- 429 - Too Many Requests (rate limited)
71
72
**Usage:**
73
74
```java
75
try {
76
GenerateContentResponse response = client.models.generateContent(
77
"invalid-model", "Hello", null);
78
} catch (ClientException e) {
79
if (e.code() == 400) {
80
System.err.println("Bad request: " + e.message());
81
} else if (e.code() == 401) {
82
System.err.println("Authentication failed");
83
} else if (e.code() == 429) {
84
System.err.println("Rate limited, retry after delay");
85
}
86
}
87
```
88
89
## ServerException
90
91
Server-side errors (HTTP 5xx status codes). Indicates issues on Google's servers.
92
93
```java { .api }
94
package com.google.genai.errors;
95
96
public final class ServerException extends ApiException {
97
public ServerException(int code, String status, String message);
98
}
99
```
100
101
**Common Status Codes:**
102
- 500 - Internal Server Error
103
- 502 - Bad Gateway
104
- 503 - Service Unavailable
105
- 504 - Gateway Timeout
106
107
**Usage:**
108
109
```java
110
try {
111
GenerateContentResponse response = client.models.generateContent(
112
"gemini-2.0-flash", "Hello", null);
113
} catch (ServerException e) {
114
System.err.println("Server error " + e.code() + ": " + e.message());
115
// Consider retry with exponential backoff
116
}
117
```
118
119
## GenAiIOException
120
121
I/O and general SDK exceptions including network errors, file operations, and serialization issues.
122
123
```java { .api }
124
package com.google.genai.errors;
125
126
public class GenAiIOException extends RuntimeException {
127
public GenAiIOException(String message);
128
public GenAiIOException(String message, Throwable cause);
129
public GenAiIOException(Throwable cause);
130
}
131
```
132
133
**Usage:**
134
135
```java
136
try {
137
File file = client.files.upload("path/to/file.jpg", null);
138
} catch (GenAiIOException e) {
139
System.err.println("I/O error: " + e.getMessage());
140
if (e.getCause() != null) {
141
System.err.println("Caused by: " + e.getCause());
142
}
143
}
144
```
145
146
## Error Handling Patterns
147
148
### Basic Try-Catch
149
150
```java
151
import com.google.genai.errors.ApiException;
152
153
try {
154
GenerateContentResponse response = client.models.generateContent(
155
"gemini-2.0-flash",
156
"Hello",
157
null
158
);
159
System.out.println(response.text());
160
} catch (ApiException e) {
161
System.err.println("Error: " + e.message());
162
}
163
```
164
165
### Specific Exception Handling
166
167
```java
168
import com.google.genai.errors.ClientException;
169
import com.google.genai.errors.ServerException;
170
import com.google.genai.errors.GenAiIOException;
171
172
try {
173
GenerateContentResponse response = client.models.generateContent(
174
"gemini-2.0-flash", "Hello", null);
175
} catch (ClientException e) {
176
// Handle client errors (4xx)
177
System.err.println("Client error: " + e.code());
178
} catch (ServerException e) {
179
// Handle server errors (5xx)
180
System.err.println("Server error: " + e.code());
181
} catch (GenAiIOException e) {
182
// Handle I/O errors
183
System.err.println("I/O error: " + e.getMessage());
184
}
185
```
186
187
### Rate Limiting with Retry
188
189
```java
190
import java.util.concurrent.TimeUnit;
191
192
int maxRetries = 3;
193
int retryCount = 0;
194
GenerateContentResponse response = null;
195
196
while (retryCount < maxRetries) {
197
try {
198
response = client.models.generateContent(
199
"gemini-2.0-flash", "Hello", null);
200
break; // Success
201
} catch (ClientException e) {
202
if (e.code() == 429 && retryCount < maxRetries - 1) {
203
retryCount++;
204
long waitMs = (long) Math.pow(2, retryCount) * 1000;
205
System.err.println("Rate limited, waiting " + waitMs + "ms");
206
TimeUnit.MILLISECONDS.sleep(waitMs);
207
} else {
208
throw e;
209
}
210
}
211
}
212
```
213
214
### Server Error Retry
215
216
```java
217
int maxRetries = 3;
218
GenerateContentResponse response = null;
219
220
for (int attempt = 0; attempt < maxRetries; attempt++) {
221
try {
222
response = client.models.generateContent(
223
"gemini-2.0-flash", "Hello", null);
224
break;
225
} catch (ServerException e) {
226
if (attempt == maxRetries - 1) {
227
throw e; // Last attempt failed
228
}
229
long waitMs = (long) Math.pow(2, attempt) * 1000;
230
System.err.println("Server error, retrying after " + waitMs + "ms");
231
Thread.sleep(waitMs);
232
}
233
}
234
```
235
236
### File Upload Error Handling
237
238
```java
239
import java.io.File as JavaFile;
240
241
try {
242
JavaFile localFile = new JavaFile("path/to/file.jpg");
243
244
if (!localFile.exists()) {
245
throw new IllegalArgumentException("File not found");
246
}
247
248
if (localFile.length() > 2L * 1024 * 1024 * 1024) {
249
throw new IllegalArgumentException("File too large (max 2GB)");
250
}
251
252
File uploadedFile = client.files.upload(localFile, null);
253
System.out.println("Uploaded: " + uploadedFile.name().orElse("N/A"));
254
255
} catch (GenAiIOException e) {
256
System.err.println("Upload failed: " + e.getMessage());
257
} catch (ApiException e) {
258
System.err.println("API error: " + e.code() + " - " + e.message());
259
}
260
```
261
262
### Streaming Error Handling
263
264
```java
265
try (ResponseStream<GenerateContentResponse> stream =
266
client.models.generateContentStream("gemini-2.0-flash", "Tell a story", null)) {
267
268
for (GenerateContentResponse chunk : stream) {
269
try {
270
System.out.print(chunk.text());
271
} catch (Exception e) {
272
System.err.println("Error processing chunk: " + e.getMessage());
273
}
274
}
275
276
} catch (ApiException e) {
277
System.err.println("Streaming error: " + e.message());
278
}
279
```
280
281
### Async Error Handling
282
283
```java
284
import java.util.concurrent.CompletableFuture;
285
286
CompletableFuture<GenerateContentResponse> future =
287
client.async.models.generateContent("gemini-2.0-flash", "Hello", null);
288
289
future
290
.thenAccept(response -> {
291
System.out.println("Success: " + response.text());
292
})
293
.exceptionally(throwable -> {
294
if (throwable instanceof ClientException) {
295
ClientException e = (ClientException) throwable;
296
System.err.println("Client error: " + e.code());
297
} else if (throwable instanceof ServerException) {
298
ServerException e = (ServerException) throwable;
299
System.err.println("Server error: " + e.code());
300
} else {
301
System.err.println("Error: " + throwable.getMessage());
302
}
303
return null;
304
});
305
```
306
307
### Safety Blocking Handling
308
309
```java
310
GenerateContentResponse response = client.models.generateContent(
311
"gemini-2.0-flash",
312
"Your prompt",
313
null
314
);
315
316
// Check if prompt was blocked
317
response.promptFeedback().ifPresent(feedback -> {
318
feedback.blockReason().ifPresent(reason -> {
319
System.err.println("Prompt blocked: " + reason);
320
feedback.safetyRatings().ifPresent(ratings -> {
321
for (SafetyRating rating : ratings) {
322
System.err.println("Category: " + rating.category().orElse("N/A"));
323
System.err.println("Probability: " + rating.probability().orElse("N/A"));
324
}
325
});
326
});
327
});
328
329
// Check if response was blocked
330
response.candidates().ifPresent(candidates -> {
331
if (!candidates.isEmpty()) {
332
Candidate first = candidates.get(0);
333
first.finishReason().ifPresent(reason -> {
334
if ("SAFETY".equals(reason)) {
335
System.err.println("Response blocked for safety");
336
first.safetyRatings().ifPresent(ratings -> {
337
// Process safety ratings
338
});
339
}
340
});
341
}
342
});
343
```
344
345
## Best Practices
346
347
### Centralized Error Handler
348
349
```java
350
public class ErrorHandler {
351
public static void handle(ApiException e) {
352
if (e instanceof ClientException) {
353
handleClientError((ClientException) e);
354
} else if (e instanceof ServerException) {
355
handleServerError((ServerException) e);
356
} else {
357
System.err.println("API error: " + e.message());
358
}
359
}
360
361
private static void handleClientError(ClientException e) {
362
switch (e.code()) {
363
case 400:
364
System.err.println("Invalid request: " + e.message());
365
break;
366
case 401:
367
System.err.println("Authentication failed");
368
break;
369
case 403:
370
System.err.println("Permission denied");
371
break;
372
case 429:
373
System.err.println("Rate limited");
374
break;
375
default:
376
System.err.println("Client error " + e.code() + ": " + e.message());
377
}
378
}
379
380
private static void handleServerError(ServerException e) {
381
System.err.println("Server error " + e.code() + ": " + e.message());
382
System.err.println("Please retry later");
383
}
384
}
385
386
// Usage
387
try {
388
GenerateContentResponse response = client.models.generateContent(...);
389
} catch (ApiException e) {
390
ErrorHandler.handle(e);
391
}
392
```
393
394
### Retry with Exponential Backoff
395
396
```java
397
public class RetryHelper {
398
public static <T> T withRetry(
399
Supplier<T> operation,
400
int maxRetries,
401
long initialDelayMs
402
) throws Exception {
403
int attempt = 0;
404
while (true) {
405
try {
406
return operation.get();
407
} catch (ServerException | ClientException e) {
408
boolean shouldRetry =
409
e instanceof ServerException ||
410
(e instanceof ClientException && ((ClientException) e).code() == 429);
411
412
if (!shouldRetry || attempt >= maxRetries - 1) {
413
throw e;
414
}
415
416
long delay = initialDelayMs * (long) Math.pow(2, attempt);
417
System.err.println("Retrying after " + delay + "ms");
418
Thread.sleep(delay);
419
attempt++;
420
}
421
}
422
}
423
}
424
425
// Usage
426
GenerateContentResponse response = RetryHelper.withRetry(
427
() -> client.models.generateContent("gemini-2.0-flash", "Hello", null),
428
3,
429
1000L
430
);
431
```
432
433
### Logging Errors
434
435
```java
436
import java.util.logging.Logger;
437
import java.util.logging.Level;
438
439
private static final Logger LOGGER = Logger.getLogger(MyClass.class.getName());
440
441
try {
442
GenerateContentResponse response = client.models.generateContent(
443
"gemini-2.0-flash", "Hello", null);
444
} catch (ApiException e) {
445
LOGGER.log(Level.SEVERE, "API error: code=" + e.code() +
446
", status=" + e.status() + ", message=" + e.message(), e);
447
} catch (GenAiIOException e) {
448
LOGGER.log(Level.SEVERE, "I/O error: " + e.getMessage(), e);
449
}
450
```
451