CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-google-genai--google-genai

Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs

Overview
Eval results
Files

error-handling.mddocs/

Error Handling

Exception hierarchy and error handling patterns for the Google GenAI SDK. All exceptions are unchecked (extend RuntimeException).

Core Imports

import com.google.genai.errors.ApiException;
import com.google.genai.errors.ClientException;
import com.google.genai.errors.ServerException;
import com.google.genai.errors.GenAiIOException;

Exception Hierarchy

RuntimeException
├── ApiException (base for API errors)
│   ├── ClientException (4xx errors)
│   └── ServerException (5xx errors)
└── GenAiIOException (I/O and SDK errors)

ApiException

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());
}

ClientException

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:

  • 400 - Bad Request (invalid parameters)
  • 401 - Unauthorized (invalid API key)
  • 403 - Forbidden (insufficient permissions)
  • 404 - Not Found (resource doesn't exist)
  • 429 - Too Many Requests (rate limited)

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");
    }
}

ServerException

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:

  • 500 - Internal Server Error
  • 502 - Bad Gateway
  • 503 - Service Unavailable
  • 504 - Gateway Timeout

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
}

GenAiIOException

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());
    }
}

Error Handling Patterns

Basic Try-Catch

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());
}

Specific Exception Handling

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());
}

Rate Limiting with Retry

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;
        }
    }
}

Server Error Retry

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);
    }
}

File Upload Error Handling

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());
}

Streaming Error Handling

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());
}

Async Error Handling

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;
    });

Safety Blocking Handling

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
                });
            }
        });
    }
});

Best Practices

Centralized Error Handler

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);
}

Retry with Exponential Backoff

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
);

Logging Errors

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-genai

docs

batch-operations.md

caching.md

chat-sessions.md

client-configuration.md

content-generation.md

embeddings-tokens.md

error-handling.md

file-search-stores.md

files-management.md

image-operations.md

index.md

live-sessions.md

model-tuning.md

operations.md

tools-functions.md

types-reference.md

video-generation.md

tile.json