Profiles·Public

@google/genai

semver>=0.1.0postconditions13functions13last verified2026-04-16

Postconditions: what we check

  • generateContent · genai-generate-content-error
    error
    Whenai.models.generateContent() called without try-catch or .catch() handler
    ThrowsApiError (name='ApiError') with .status (HTTP status code) and .message. Common statuses: 400 (invalid request/model), 401 (missing API key), 403 (API key invalid/permission denied), 429 (quota exceeded/rate limit), 500 (internal server error), 503 (service unavailable).
    Required handlingCaller MUST wrap await ai.models.generateContent() in try-catch or chain .catch(). Uncaught ApiError causes unhandled promise rejection — AI features silently fail and users see broken responses or error pages. try { const response = await ai.models.generateContent({ model: 'gemini-2.0-flash', contents: prompt, }); return response.text; } catch (error) { if (error instanceof ApiError) { if (error.status === 429) throw new Error('Rate limited'); } throw error; }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[1][2]
  • generateContentStream · genai-generate-content-stream-error
    error
    Whenai.models.generateContentStream() called without try-catch or .catch() handler
    ThrowsApiError (name='ApiError') with .status and .message on HTTP failure. The initial await can throw before any chunks arrive.
    Required handlingCaller MUST wrap await ai.models.generateContentStream() in try-catch. Errors on the initial call propagate before any stream chunks are yielded.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[1][2]
  • generateImages · genai-generate-images-error
    error
    Whenai.models.generateImages() called without try-catch or .catch() handler
    ThrowsApiError (name='ApiError') with .status and .message on HTTP failure.
    Required handlingCaller MUST wrap await ai.models.generateImages() in try-catch.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[3]
  • embedContent · genai-embed-content-error
    error
    Whenai.models.embedContent() called without try-catch or .catch() handler
    ThrowsApiError (name='ApiError') with .status and .message on HTTP failure.
    Required handlingCaller MUST wrap await ai.models.embedContent() in try-catch. This is a common antipattern — seen unprotected in cherry-studio-app (2.9k stars).
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[3]
  • sendMessage · genai-send-message-no-error-handling
    error
    Whenchat.sendMessage() called in async context without surrounding try-catch. ApiError propagates as unhandled promise rejection.
    ThrowsApiError (name='ApiError') with .status (HTTP status code) and .message. Common statuses: 400 (invalid request/model), 401 (missing API key), 403 (API key invalid/permission denied), 429 (quota exceeded/rate limit), 500 (internal server error), 503 (service unavailable). Error (generic) for mimeType or history validation failures.
    Required handlingCaller MUST wrap await chat.sendMessage() in try-catch. Chat sessions are stateful — an unhandled error during a turn corrupts the conversational state. The SDK resets sendPromise on error, so subsequent sends can proceed, but the failed turn is recorded as invalid in comprehensive history. try { const response = await chat.sendMessage({ message: userInput }); return response.text; } catch (error) { if (error instanceof ApiError) { if (error.status === 429) { // Rate limit — retry with backoff } else if (error.status === 400) { // Invalid content — surface to user } } throw error; }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[4][5]
  • sendMessageStream · genai-send-message-stream-no-error-handling
    error
    Whenchat.sendMessageStream() called in async context without surrounding try-catch. ApiError propagates as unhandled promise rejection on the initial await.
    ThrowsApiError (name='ApiError') with .status and .message on HTTP failure before any chunks arrive. Errors during streaming (mid-stream) also throw ApiError on the next chunk iteration.
    Required handlingCaller MUST wrap await chat.sendMessageStream() in try-catch. The initial await can throw before any chunks arrive. Streaming errors mid-response also propagate as ApiError on the async generator. try { const stream = await chat.sendMessageStream({ message: userInput }); for await (const chunk of stream) { process.stdout.write(chunk.text ?? ''); } } catch (error) { if (error instanceof ApiError) { // Handle network error or API failure } throw error; }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[4][6]
  • upload · genai-files-upload-no-error-handling
    error
    Whenai.files.upload() called without try-catch. Upload protocol errors, quota exceeded, or API failures result in unhandled promise rejection.
    ThrowsApiError (name='ApiError') with .status and .message for HTTP failures (401 missing API key, 403 storage quota exceeded, 413 file too large, 429 rate limit, 500 server error). Error (generic) for mimeType inference failure ('Can not determine mimeType'), upload protocol failures ('Failed to get upload url'), finalization errors ('Failed to upload file: Upload status is not finalized'), or when called on Vertex AI ('Vertex AI does not support uploading files').
    Required handlingCaller MUST wrap await ai.files.upload() in try-catch. Large file uploads are particularly prone to failure mid-upload (network interruption, quota). The Files API has strict limits: 2 GB per file, 20 GB project storage. try { const file = await ai.files.upload({ file: '/path/to/video.mp4', config: { mimeType: 'video/mp4' }, }); // Use file.name in subsequent generateContent calls } catch (error) { if (error instanceof ApiError && error.status === 403) { throw new Error('File storage quota exceeded'); } throw error; }
    costhighin prodimmediate exceptionusers seelost datavisibilitysilent
    Sources[7][8]
  • countTokens · genai-count-tokens-no-error-handling
    warning
    Whenai.models.countTokens() called without try-catch. Used as pre-flight check to measure token count before sending large prompts. ApiError on invalid model name or API failure silently breaks the pre-flight guard.
    ThrowsApiError (name='ApiError') with .status and .message on HTTP failure. 404: model name not found or invalid format. 400: invalid content (e.g., empty contents array). 401: missing or invalid API key. 429: rate limit exceeded (countTokens has its own rate limits, separate from generateContent).
    Required handlingCaller MUST wrap await ai.models.countTokens() in try-catch. If the pre-flight check throws and the error is swallowed, the caller proceeds with an untested prompt that may exceed context limits. try { const result = await ai.models.countTokens({ model: 'gemini-2.0-flash', contents: largePrompt, }); if (result.totalTokens > 1000000) { throw new Error('Prompt too large for model context window'); } } catch (error) { if (error instanceof ApiError) { // Pre-flight failed — proceed with caution or abort } throw error; }
    costlowin prodimmediate exceptionusers seedegraded performancevisibilitysilent
    Sources[9]
  • create · genai-caches-create-no-error-handling
    error
    Whenai.caches.create() called without try-catch. API failures (unsupported model, token threshold not met, quota exceeded) result in unhandled promise rejection.
    ThrowsApiError (name='ApiError') with .status and .message on HTTP failure. 400: model does not support context caching, or content below minimum token threshold (1,024 tokens for Flash models, 4,096 for Pro models). 401: missing or invalid API key. 403: quota exceeded or billing issue. 404: model not found. 429: rate limit exceeded.
    Required handlingCaller MUST wrap await ai.caches.create() in try-catch. A 400 error indicates either an incompatible model or insufficient content — both require different resolution strategies. try { const cache = await ai.caches.create({ model: 'gemini-2.5-flash', config: { contents: largeSystemContext, ttl: '3600s', }, }); // Use cache.name in subsequent generateContent calls } catch (error) { if (error instanceof ApiError && error.status === 400) { // Either model doesn't support caching or content < minimum tokens } throw error; }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilitysilent
    Sources[10][11]
  • uploadToFileSearchStore · genai-file-search-stores-upload-error
    error
    Whenai.fileSearchStores.uploadToFileSearchStore() called without try-catch. Three distinct throw paths: (1) Vertex AI client (always throws — method unsupported), (2) MIME type cannot be inferred (no extension on string path / no Blob.type), (3) upload location cannot be established (HTTP error from upload-protocol initiation).
    ThrowsError on Vertex AI client (method not supported). Error on MIME type inference failure when mimeType not provided in config. Error on upload-location establishment failure. ApiError on 4xx/5xx HTTP responses from upload-protocol layer.
    Required handlingCaller MUST wrap await ai.fileSearchStores.uploadToFileSearchStore() in try-catch. RAG ingestion pipelines that silently swallow these errors end up with empty file search stores and degraded retrieval quality that is hard to detect downstream. try { const op = await ai.fileSearchStores.uploadToFileSearchStore({ fileSearchStoreName: 'fileSearchStores/foo-bar', file: 'doc.pdf', config: { mimeType: 'application/pdf' }, }); // Poll op until op.done === true } catch (error) { if (error instanceof ApiError) { // HTTP error during upload-location establishment } throw error; }
    costmediumin prodimmediate exceptionusers seedegraded performancevisibilitysilent
    Sources[12][13]
  • importFile · genai-file-search-stores-import-file-error
    error
    Whenai.fileSearchStores.importFile() called without try-catch.
    ThrowsApiError with .status and .message on HTTP failure during operation initiation. Common statuses: 400 (source file not found / unsupported format), 401 (missing API key), 403 (quota / permission), 404 (fileSearchStoreName not found), 429 (rate limit).
    Required handlingCaller MUST wrap await ai.fileSearchStores.importFile() in try-catch. The returned Operation must additionally be polled — chunking and embedding failures surface on the polled Operation.error field, not from the initial Promise. try { const op = await ai.fileSearchStores.importFile({ fileSearchStoreName: 'fileSearchStores/foo', fileName: 'files/bar', }); // Poll op via ai.operations.get() until op.done } catch (error) { if (error instanceof ApiError) { // Operation never started — bad request or auth failure } throw error; }
    costmediumin prodimmediate exceptionusers seedegraded performancevisibilitysilent
  • tune · genai-tunings-tune-error
    error
    Whenai.tunings.tune() called without try-catch.
    ThrowsApiError (name='ApiError') with .status and .message on HTTP failure. Common statuses: 400 (invalid trainingDataset format / unsupported baseModel), 401 (missing API key), 403 (tuning quota exceeded / permission denied — fine-tuning requires elevated access), 404 (baseModel does not support tuning), 429 (rate limit on tuning submissions), 503 (tuning service unavailable).
    Required handlingCaller MUST wrap await ai.tunings.tune() in try-catch. Fine-tuning jobs cost money to run — a swallowed ApiError on submission means the caller incorrectly believes the job is queued and may double-submit or never poll for completion, masking the real failure. try { const job = await ai.tunings.tune({ baseModel: 'models/gemini-2.0-flash', trainingDataset: { gcsUri: 'gs://my-bucket/train.jsonl' }, config: { tunedModelDisplayName: 'my-tuned-model' }, }); // Poll ai.tunings.get({ name: job.name }) until terminal state } catch (error) { if (error instanceof ApiError) { if (error.status === 403) { // Quota or permission — escalate, don't retry blindly } } throw error; }
    costmediumin prodimmediate exceptionusers seedegraded performancevisibilitysilent
    Sources[15][16]
  • createEmbeddings · genai-batches-create-embeddings-error
    error
    Whenai.batches.createEmbeddings() called without try-catch.
    ThrowsApiError with .status and .message on HTTP failure. Common statuses: 400 (invalid src format / model does not support batch embeddings), 401 (missing API key), 403 (batch quota exceeded), 404 (model not found), 429 (rate limit).
    Required handlingCaller MUST wrap await ai.batches.createEmbeddings() in try-catch. Batch embedding jobs are typically background pipelines — a swallowed submission error leaves the pipeline silently idle while downstream consumers wait for embeddings that will never arrive. try { const job = await ai.batches.createEmbeddings({ model: 'text-embedding-004', src: { fileName: 'files/my-input' }, }); // Poll ai.batches.get({ name: job.name }) until terminal state } catch (error) { if (error instanceof ApiError) { if (error.status === 429) throw new Error('Batch rate limited'); } throw error; }
    costmediumin prodimmediate exceptionusers seedegraded performancevisibilitysilent
    Sources[17][18]

Sources

Every postcondition cites at least one of these. Grouped by source type; numbered to match the footnotes above.

Official documentation
  • [7]
    ai.google.dev/gemini-api/docs/files
    Files
  • [10]
    ai.google.dev/gemini-api/docs/caching
    Caching
  • [13]
    ai.google.dev/gemini-api/docs/file-search
    File Search
  • [14]
    google.aip.dev/151
    151
  • [16]
    ai.google.dev/gemini-api/docs/model-tuning
    Model Tuning
  • [18]
    ai.google.dev/gemini-api/docs/batch-mode
    Batch Mode
Source code

Research notes

Curator notes from SOURCES.md captured when the profile was written so you can verify the reasoning, not just the rules.

Sources — @google/genai

Fetched URLs (2026-04-02)

URLSummary
https://raw.githubusercontent.com/googleapis/js-genai/main/README.mdMain README with error handling examples showing ApiError class
https://raw.githubusercontent.com/googleapis/js-genai/main/src/errors.tsSource for ApiError class — extends Error, has status and message properties
https://raw.githubusercontent.com/googleapis/js-genai/main/src/models.tsSource for all model methods — generateContent, generateContentStream, generateImages, embedContent
https://ai.google.dev/api/generate-contentGemini API generate content reference

Key Evidence

  1. ApiError is the single error type thrown by all ai.models.* async methods
  2. ApiError.status exposes HTTP status code (401, 403, 429, 400, 500, 503)
  3. SDK README explicitly shows try-catch pattern for generateContent
  4. Real-world usage in cline/cline (59k stars) shows proper ApiError handling with 429 detection
  5. Real-world antipattern in CherryHQ/cherry-studio-app: embedContent and models.list() called without try-catch
Need a different package?
Request a profile