Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs
Exception hierarchy and error handling patterns for the Google GenAI SDK. All exceptions are unchecked (extend RuntimeException).
import com.google.genai.errors.ApiException;
import com.google.genai.errors.ClientException;
import com.google.genai.errors.ServerException;
import com.google.genai.errors.GenAiIOException;RuntimeException
├── ApiException (base for API errors)
│ ├── ClientException (4xx errors)
│ └── ServerException (5xx errors)
└── GenAiIOException (I/O and SDK errors)Base class for all API-related errors.
package com.google.genai.errors;
public class ApiException extends RuntimeException {
public ApiException(int code, String status, String message);
public int code();
public String status();
public String message();
public static void throwFromResponse(Response response);
}Usage:
try {
GenerateContentResponse response = client.models.generateContent(
"gemini-2.0-flash", "Hello", null);
} catch (ApiException e) {
System.err.println("API Error " + e.code() + ": " + e.message());
System.err.println("Status: " + e.status());
}Client-side errors (HTTP 4xx status codes). Indicates issues with the request such as invalid parameters, authentication failures, or rate limiting.
package com.google.genai.errors;
public final class ClientException extends ApiException {
public ClientException(int code, String status, String message);
}Common Status Codes:
Usage:
try {
GenerateContentResponse response = client.models.generateContent(
"invalid-model", "Hello", null);
} catch (ClientException e) {
if (e.code() == 400) {
System.err.println("Bad request: " + e.message());
} else if (e.code() == 401) {
System.err.println("Authentication failed");
} else if (e.code() == 429) {
System.err.println("Rate limited, retry after delay");
}
}Server-side errors (HTTP 5xx status codes). Indicates issues on Google's servers.
package com.google.genai.errors;
public final class ServerException extends ApiException {
public ServerException(int code, String status, String message);
}Common Status Codes:
Usage:
try {
GenerateContentResponse response = client.models.generateContent(
"gemini-2.0-flash", "Hello", null);
} catch (ServerException e) {
System.err.println("Server error " + e.code() + ": " + e.message());
// Consider retry with exponential backoff
}I/O and general SDK exceptions including network errors, file operations, and serialization issues.
package com.google.genai.errors;
public class GenAiIOException extends RuntimeException {
public GenAiIOException(String message);
public GenAiIOException(String message, Throwable cause);
public GenAiIOException(Throwable cause);
}Usage:
try {
File file = client.files.upload("path/to/file.jpg", null);
} catch (GenAiIOException e) {
System.err.println("I/O error: " + e.getMessage());
if (e.getCause() != null) {
System.err.println("Caused by: " + e.getCause());
}
}import com.google.genai.errors.ApiException;
try {
GenerateContentResponse response = client.models.generateContent(
"gemini-2.0-flash",
"Hello",
null
);
System.out.println(response.text());
} catch (ApiException e) {
System.err.println("Error: " + e.message());
}import com.google.genai.errors.ClientException;
import com.google.genai.errors.ServerException;
import com.google.genai.errors.GenAiIOException;
try {
GenerateContentResponse response = client.models.generateContent(
"gemini-2.0-flash", "Hello", null);
} catch (ClientException e) {
// Handle client errors (4xx)
System.err.println("Client error: " + e.code());
} catch (ServerException e) {
// Handle server errors (5xx)
System.err.println("Server error: " + e.code());
} catch (GenAiIOException e) {
// Handle I/O errors
System.err.println("I/O error: " + e.getMessage());
}import java.util.concurrent.TimeUnit;
int maxRetries = 3;
int retryCount = 0;
GenerateContentResponse response = null;
while (retryCount < maxRetries) {
try {
response = client.models.generateContent(
"gemini-2.0-flash", "Hello", null);
break; // Success
} catch (ClientException e) {
if (e.code() == 429 && retryCount < maxRetries - 1) {
retryCount++;
long waitMs = (long) Math.pow(2, retryCount) * 1000;
System.err.println("Rate limited, waiting " + waitMs + "ms");
TimeUnit.MILLISECONDS.sleep(waitMs);
} else {
throw e;
}
}
}int maxRetries = 3;
GenerateContentResponse response = null;
for (int attempt = 0; attempt < maxRetries; attempt++) {
try {
response = client.models.generateContent(
"gemini-2.0-flash", "Hello", null);
break;
} catch (ServerException e) {
if (attempt == maxRetries - 1) {
throw e; // Last attempt failed
}
long waitMs = (long) Math.pow(2, attempt) * 1000;
System.err.println("Server error, retrying after " + waitMs + "ms");
Thread.sleep(waitMs);
}
}import java.io.File as JavaFile;
try {
JavaFile localFile = new JavaFile("path/to/file.jpg");
if (!localFile.exists()) {
throw new IllegalArgumentException("File not found");
}
if (localFile.length() > 2L * 1024 * 1024 * 1024) {
throw new IllegalArgumentException("File too large (max 2GB)");
}
File uploadedFile = client.files.upload(localFile, null);
System.out.println("Uploaded: " + uploadedFile.name().orElse("N/A"));
} catch (GenAiIOException e) {
System.err.println("Upload failed: " + e.getMessage());
} catch (ApiException e) {
System.err.println("API error: " + e.code() + " - " + e.message());
}try (ResponseStream<GenerateContentResponse> stream =
client.models.generateContentStream("gemini-2.0-flash", "Tell a story", null)) {
for (GenerateContentResponse chunk : stream) {
try {
System.out.print(chunk.text());
} catch (Exception e) {
System.err.println("Error processing chunk: " + e.getMessage());
}
}
} catch (ApiException e) {
System.err.println("Streaming error: " + e.message());
}import java.util.concurrent.CompletableFuture;
CompletableFuture<GenerateContentResponse> future =
client.async.models.generateContent("gemini-2.0-flash", "Hello", null);
future
.thenAccept(response -> {
System.out.println("Success: " + response.text());
})
.exceptionally(throwable -> {
if (throwable instanceof ClientException) {
ClientException e = (ClientException) throwable;
System.err.println("Client error: " + e.code());
} else if (throwable instanceof ServerException) {
ServerException e = (ServerException) throwable;
System.err.println("Server error: " + e.code());
} else {
System.err.println("Error: " + throwable.getMessage());
}
return null;
});GenerateContentResponse response = client.models.generateContent(
"gemini-2.0-flash",
"Your prompt",
null
);
// Check if prompt was blocked
response.promptFeedback().ifPresent(feedback -> {
feedback.blockReason().ifPresent(reason -> {
System.err.println("Prompt blocked: " + reason);
feedback.safetyRatings().ifPresent(ratings -> {
for (SafetyRating rating : ratings) {
System.err.println("Category: " + rating.category().orElse("N/A"));
System.err.println("Probability: " + rating.probability().orElse("N/A"));
}
});
});
});
// Check if response was blocked
response.candidates().ifPresent(candidates -> {
if (!candidates.isEmpty()) {
Candidate first = candidates.get(0);
first.finishReason().ifPresent(reason -> {
if ("SAFETY".equals(reason)) {
System.err.println("Response blocked for safety");
first.safetyRatings().ifPresent(ratings -> {
// Process safety ratings
});
}
});
}
});public class ErrorHandler {
public static void handle(ApiException e) {
if (e instanceof ClientException) {
handleClientError((ClientException) e);
} else if (e instanceof ServerException) {
handleServerError((ServerException) e);
} else {
System.err.println("API error: " + e.message());
}
}
private static void handleClientError(ClientException e) {
switch (e.code()) {
case 400:
System.err.println("Invalid request: " + e.message());
break;
case 401:
System.err.println("Authentication failed");
break;
case 403:
System.err.println("Permission denied");
break;
case 429:
System.err.println("Rate limited");
break;
default:
System.err.println("Client error " + e.code() + ": " + e.message());
}
}
private static void handleServerError(ServerException e) {
System.err.println("Server error " + e.code() + ": " + e.message());
System.err.println("Please retry later");
}
}
// Usage
try {
GenerateContentResponse response = client.models.generateContent(...);
} catch (ApiException e) {
ErrorHandler.handle(e);
}public class RetryHelper {
public static <T> T withRetry(
Supplier<T> operation,
int maxRetries,
long initialDelayMs
) throws Exception {
int attempt = 0;
while (true) {
try {
return operation.get();
} catch (ServerException | ClientException e) {
boolean shouldRetry =
e instanceof ServerException ||
(e instanceof ClientException && ((ClientException) e).code() == 429);
if (!shouldRetry || attempt >= maxRetries - 1) {
throw e;
}
long delay = initialDelayMs * (long) Math.pow(2, attempt);
System.err.println("Retrying after " + delay + "ms");
Thread.sleep(delay);
attempt++;
}
}
}
}
// Usage
GenerateContentResponse response = RetryHelper.withRetry(
() -> client.models.generateContent("gemini-2.0-flash", "Hello", null),
3,
1000L
);import java.util.logging.Logger;
import java.util.logging.Level;
private static final Logger LOGGER = Logger.getLogger(MyClass.class.getName());
try {
GenerateContentResponse response = client.models.generateContent(
"gemini-2.0-flash", "Hello", null);
} catch (ApiException e) {
LOGGER.log(Level.SEVERE, "API error: code=" + e.code() +
", status=" + e.status() + ", message=" + e.message(), e);
} catch (GenAiIOException e) {
LOGGER.log(Level.SEVERE, "I/O error: " + e.getMessage(), e);
}Install with Tessl CLI
npx tessl i tessl/maven-com-google-genai--google-genaidocs