Profiles·Public

googleapis

semver>=39.1.0 <200.0.0postconditions28functions16last verified2026-06-25coverage score89%

Postconditions: what we check

  • channels.list · error-api-call
    error
    WhenAsync googleapis API call (e.g., youtube.channels.list, drive.files.list, gmail.users.messages.send) is not wrapped in a try-catch block. All googleapis methods throw GaxiosError on failure.
    ThrowsGaxiosError
    Required handlingCaller MUST wrap googleapis API calls in try-catch. Check error.status for HTTP status codes: 401 → auth failure (token expired/invalid) 403 → quota exceeded or insufficient permissions 404 → resource not found 429 → rate limit exceeded 5xx → Google server error Use instanceof GaxiosError (from 'gaxios' or 'googleapis-common') for type guard.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[1][2]
  • videos.insert · error-api-call
    error
    Whenyoutube.videos.insert() is not wrapped in a try-catch block. Throws GaxiosError on auth/quota/upload failure.
    ThrowsGaxiosError
    Required handlingCaller MUST wrap youtube.videos.insert() in try-catch. Video uploads can fail with quota errors (403), auth errors (401), or invalid request errors (400).
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[1]
  • files.list · error-api-call
    error
    Whendrive.files.list() not wrapped in try-catch
    ThrowsGaxiosError
    Required handlingWrap in try-catch, check error.status
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[1]
  • messages.send · gmail-messages-send-auth-error
    error
    Whengmail.users.messages.send() is called without try-catch and the OAuth token is expired, invalid, or missing the gmail.send scope.
    ThrowsGaxiosError with status 401, error.code === 'authError'
    Required handlingWrap in try-catch. Check error.status === 401 and refresh the OAuth token. Verify the token has the gmail.send scope (https://mail.google.com/). Re-authenticate the user if the refresh token is also invalid.
    costhighin prodimmediate exceptionusers seelost transactionvisibilitysilent
    Sources[3]
  • messages.send · gmail-messages-send-quota-exceeded
    error
    Whengmail.users.messages.send() is called without try-catch and the project or user has exhausted the Gmail API daily quota. Common in email automation services, bulk notification senders, or apps that send per-user emails without rate limiting.
    ThrowsGaxiosError with status 403, error.code === 'dailyLimitExceeded' or 'rateLimitExceeded' or 'userRateLimitExceeded'
    Required handlingWrap in try-catch. Check error.status === 403. For dailyLimitExceeded: queue messages for the next day or upgrade quota. For userRateLimitExceeded (100 requests/user/100s): implement exponential backoff and queue unsent messages. For rateLimitExceeded (project-level): use exponential backoff.
    costhighin prodsilent failureusers seelost transactionvisibilitysilent
    Sources[3]
  • messages.list · gmail-messages-list-auth-error
    error
    Whengmail.users.messages.list() called without try-catch and the OAuth access token has expired. Very common in CRM integrations where tokens expire between sync cycles.
    ThrowsGaxiosError with status 401, error.code === 'authError'
    Required handlingWrap in try-catch. Check error.status === 401. Trigger OAuth token refresh flow. If refresh fails (refresh token revoked), mark the inbox connection as disconnected and notify the user.
    costmediumin prodimmediate exceptionusers seedegraded performancevisibilitysilent
    Sources[3]
  • messages.list · gmail-messages-list-rate-limit
    warning
    Whengmail.users.messages.list() called without try-catch and rate limit exceeded. Common when syncing large inboxes or polling too frequently.
    ThrowsGaxiosError with status 429 or 403 with rateLimitExceeded reason
    Required handlingWrap in try-catch. Implement exponential backoff for 429/403 errors. Respect the Retry-After header if present. For inbox sync use cases, use Gmail Push Notifications (watch) instead of polling.
    costlowin prodimmediate exceptionusers seedegraded performancevisibilitysilent
    Sources[3]
  • files.create · drive-files-create-storage-quota-exceeded
    error
    Whendrive.files.create() called without try-catch and the target user's Google Drive storage is full. Critical for apps that write files to user-owned drives — e.g., document export features, automated report delivery to Drive.
    ThrowsGaxiosError with status 403, error.code === 'storageQuotaExceeded'
    Required handlingWrap in try-catch. Check error.status === 403 and inspect error.response.data for 'storageQuotaExceeded'. Notify the user that their Drive storage is full. Do NOT silently retry — the operation will continue to fail until the user frees storage space.
    costmediumin prodimmediate exceptionusers seelost transactionvisibilitysilent
    Sources[4]
  • files.create · drive-files-create-insufficient-permissions
    error
    Whendrive.files.create() called without try-catch when the authenticated user lacks write access to the target parent folder (Shared Drive or shared folder). Common when apps try to create files in a workspace folder the user can only read.
    ThrowsGaxiosError with status 403, error.code === 'insufficientFilePermissions'
    Required handlingWrap in try-catch. Check error.status === 403. Distinguish from quota errors by reading error.response.data.error.errors[0].reason. Display a clear permission error message — silently ignoring causes data loss.
    costmediumin prodimmediate exceptionusers seelost datavisibilitysilent
    Sources[4]
  • files.create · drive-files-create-rate-limit
    warning
    Whendrive.files.create() called in a tight loop without try-catch. Apps that upload many files in batches (e.g., bulk document generation) easily hit the Drive API rate limits (userRateLimitExceeded: 10 req/s/user).
    ThrowsGaxiosError with status 403 with rateLimitExceeded or userRateLimitExceeded reason, or status 429
    Required handlingWrap in try-catch. Implement exponential backoff for all 403 rate-limit and 429 errors. For bulk uploads, use a queue with rate limiting (e.g., p-limit, p-queue) rather than Promise.all().
    costlowin prodimmediate exceptionusers seelost transactionvisibilityvisible
    Sources[4]
  • events.insert · calendar-events-insert-auth-error
    error
    Whencalendar.events.insert() called without try-catch and the OAuth token is expired or lacks the calendar write scope. Common in booking systems where the token expires between user authentication and event creation.
    ThrowsGaxiosError with status 401, error.code === 'authError'
    Required handlingWrap in try-catch. Check error.status === 401. Trigger OAuth token refresh. Required scope for creating events: https://www.googleapis.com/auth/calendar or https://www.googleapis.com/auth/calendar.events
    costhighin prodimmediate exceptionusers seelost transactionvisibilitysilent
    Sources[5]
  • events.insert · calendar-events-insert-quota-exceeded
    warning
    Whencalendar.events.insert() called without try-catch and the project quota or per-user rate limit is exceeded. Calendar API has lower quotas than other Google APIs — 10,000 req/day/user for write operations.
    ThrowsGaxiosError with status 403, error.code === 'quotaExceeded' or 'rateLimitExceeded' or 'userRateLimitExceeded'
    Required handlingWrap in try-catch. Implement exponential backoff for 403 quota errors. For high-volume scheduling, use batched requests or the Calendar Batch API. Check error.response.data.error.errors[0].reason for exact quota type.
    costmediumin prodimmediate exceptionusers seelost transactionvisibilityvisible
    Sources[5]
  • events.insert · calendar-events-insert-calendar-not-found
    error
    Whencalendar.events.insert() called without try-catch with a calendarId that does not exist or to which the user no longer has access. Common when a user deletes or unshares a calendar that the app stored the ID of.
    ThrowsGaxiosError with status 404, error.code === 'notFound'
    Required handlingWrap in try-catch. Check error.status === 404. Fall back to the primary calendar ('primary') or prompt the user to re-select a calendar. Do not cache calendarIds permanently — they can be deleted.
    costmediumin prodimmediate exceptionusers seelost transactionvisibilitysilent
    Sources[5]
  • events.list · calendar-events-list-sync-token-invalid
    error
    Whencalendar.events.list() called without try-catch using a stored syncToken parameter for incremental sync, and the token has expired. This is a Calendar-specific behavior: syncTokens expire after roughly 6 months of inactivity or on some structural changes to the calendar.
    ThrowsGaxiosError with status 410, error.code === 'fullSyncRequired' or 'updatedMinTooLongAgo'
    Required handlingWrap in try-catch. Check error.status === 410. Discard the stored syncToken and perform a full re-sync (call events.list without syncToken to get a fresh token). Apps that use incremental sync MUST handle 410 Gone explicitly — omitting this handler causes permanent sync failure after token expiry.
    costmediumin prodimmediate exceptionusers seedegraded performancevisibilitysilent
    Sources[5]
  • events.list · calendar-events-list-auth-error
    error
    Whencalendar.events.list() called without try-catch and the OAuth access token has expired. Very common in background jobs that poll for calendar changes.
    ThrowsGaxiosError with status 401, error.code === 'authError'
    Required handlingWrap in try-catch. Check error.status === 401. Trigger OAuth token refresh. If the refresh token has been revoked, notify the user and mark the calendar connection as disconnected.
    costmediumin prodimmediate exceptionusers seedegraded performancevisibilitysilent
    Sources[5]
  • values.update · sheets-values-update-rate-limit
    warning
    Whensheets.spreadsheets.values.update() called without try-catch in a loop or rapid succession. The Sheets API enforces 60 write requests/user/min and 300 write requests/project/min. Apps that write many cells in a loop (e.g., syncing CRM data to a spreadsheet row by row) will hit this quickly.
    ThrowsGaxiosError with status 429
    Required handlingWrap in try-catch. Check error.status === 429. Use batchUpdate (writes to multiple ranges in one request) instead of repeated values.update calls. Implement exponential backoff. Per-minute quotas reset every 60 seconds.
    costmediumin prodimmediate exceptionusers seedegraded performancevisibilitysilent
    Sources[6]
  • values.update · sheets-values-update-not-found
    error
    Whensheets.spreadsheets.values.update() called without try-catch with a spreadsheetId or range that does not exist or is inaccessible. Common when apps store a spreadsheet ID from OAuth setup that the user later deletes or stops sharing.
    ThrowsGaxiosError with status 404
    Required handlingWrap in try-catch. Check error.status === 404. Prompt the user to reconnect their spreadsheet. Do not silently retry — the spreadsheet is gone.
    costhighin prodimmediate exceptionusers seelost datavisibilitysilent
    Sources[6]
  • spreadsheets.batchUpdate · sheets-batch-update-atomic-failure
    error
    Whensheets.spreadsheets.batchUpdate() called without try-catch with a batch containing one or more invalid requests. batchUpdate is atomic: if any single sub-request fails validation or execution, the entire batch is rolled back. No partial writes occur. Common error source: invalid range notation, out-of-bounds sheet indices, or conflicting formatting requests.
    ThrowsGaxiosError with status 400, containing details of the first invalid request
    Required handlingWrap in try-catch. For 400 errors, inspect error.response.data.error.message to identify which sub-request failed. Validate all requests before submission. Consider splitting large batches to isolate failures.
    costmediumin prodimmediate exceptionusers seelost datavisibilitysilent
    Sources[6]
  • permissions.create · drive-permissions-create-sharing-rate-limit
    error
    Whendrive.permissions.create() called without try-catch in a loop that shares many files (e.g., bulk onboarding, batch report distribution). Drive enforces a per-user sharingRateLimitExceeded distinct from the general rateLimitExceeded — it triggers on share velocity, not request velocity, and is often linked to notification-email bursts.
    ThrowsGaxiosError with status 403, error.response.data.error.errors[0].reason === 'sharingRateLimitExceeded'
    Required handlingWrap in try-catch. For 403 errors, inspect error.response.data.error.errors[0].reason. When reason === 'sharingRateLimitExceeded', stop the bulk share loop and back off significantly (minutes, not seconds). Consider setting sendNotificationEmail: false during bulk shares — Google's docs flag notification email volume as a primary trigger. For long-running automation, use a service account with domain-wide delegation.
    costmediumin prodimmediate exceptionusers seelost transactionvisibilitysilent
    Sources[4]
  • permissions.create · drive-permissions-create-insufficient-permissions
    error
    Whendrive.permissions.create() called without try-catch when the authenticated user lacks the right to grant access to the target file (e.g., the user is a writer but not the owner, or attempting to share a file inside a Shared Drive where the user lacks Manager role). Common in SaaS apps that share files owned by an end user but accessed via a service account without sufficient role.
    ThrowsGaxiosError with status 403, error.response.data.error.errors[0].reason === 'insufficientFilePermissions'
    Required handlingWrap in try-catch. For 403 errors, inspect error.response.data.error.errors[0].reason. When reason === 'insufficientFilePermissions', surface a clear error to the user that they (or the service account) must be an owner / Shared Drive Manager to grant new access. Do NOT retry — the call will continue to fail until the underlying role is upgraded. Distinguish this from 'sharingRateLimitExceeded' and 'appNotAuthorizedToFile' which require different remediation.
    costmediumin prodimmediate exceptionusers seelost transactionvisibilitysilent
    Sources[4]
  • permissions.create · drive-permissions-create-invalid-sharing-request
    error
    Whendrive.permissions.create() called without try-catch with an invalid permission body — most commonly an email address that doesn't exist, a domain restriction that blocks the share, or an ACL combination disallowed by the workspace admin (e.g., trying to share externally when external sharing is disabled).
    ThrowsGaxiosError with status 400, error.response.data.error.errors[0].reason === 'invalidSharingRequest'
    Required handlingWrap in try-catch. For 400 errors with reason === 'invalidSharingRequest', read error.response.data.error.message — Google embeds the specific cause (bad email, domain restriction, ACL conflict). Display this to the user rather than failing silently. Do NOT retry without fixing the input.
    costlowin prodimmediate exceptionusers seelost transactionvisibilitysilent
    Sources[4]
  • messages.watch · gmail-watch-pubsub-permission-missing
    error
    Whengmail.users.watch() called without try-catch when the Pub/Sub topic does not exist or the Gmail push service account (gmail-api-push@system.gserviceaccount.com) has not been granted Publish permission on the topic. This is the most common misconfiguration in production deployments.
    ThrowsGaxiosError with status 403, error.response.data.error.message contains 'topic'
    Required handlingWrap in try-catch. A 403 with 'topic' in the error message indicates Pub/Sub topic misconfiguration — the topic may not exist, or the Gmail push service account lacks Publish rights. Do NOT retry until the IAM permissions are fixed. Log the full error.response.data.error for diagnosis — the message details which condition failed.
    costhighin prodimmediate exceptionusers seeservice unavailablevisibilitysilent
    Sources[7]
  • messages.watch · gmail-watch-expiry-not-renewed
    warning
    Whengmail.users.watch() is set up once at startup but never re-called. The watch expires after 7 days. After expiration, no push notifications are delivered but the app receives no error — notifications simply stop arriving. This is the primary "works in staging, fails in production after first week" pattern for Gmail integrations.
    ThrowsNo error thrown — silent failure: notifications stop arriving after ~7 days
    Required handlingSchedule a daily or weekly job to call watch() again (every 1-3 days is safe). The watch() call is idempotent — re-registering before expiry simply resets the timer. Store expiration from response.expiration and alert if the renewal job fails. Implement periodic history.list() fallback polling to catch missed notifications.
    costhighin prodsilent failureusers seelost datavisibilitysilent
    Sources[7]
  • files.delete · drive-files-delete-no-try-catch
    error
    Whendrive.files.delete() called without try-catch. The file may not exist (404), the user may lack delete rights (403 insufficientFilePermissions), or the file may be in a Shared Drive where the user is not an organizer.
    ThrowsGaxiosError with status 403 (reason: 'insufficientFilePermissions') or 404 (reason: 'notFound')
    Required handlingWrap in try-catch. For 404 errors, the file was already deleted or was never accessible — treat as idempotent success for cleanup jobs. For 403 errors with reason === 'insufficientFilePermissions', the caller lacks delete rights (may be a writer or commenter, not owner). For Shared Drive files (403 with 'teamDriveMembershipRequired' or lacking organizer role), surface the error clearly rather than retrying. IMPORTANT: because this operation is irreversible, confirm the correct fileId before calling — there is no trash to recover from.
    costhighin prodimmediate exceptionusers seelost transactionvisibilitysilent
    Sources[4]
  • files.delete · drive-files-delete-folder-cascade
    error
    Whendrive.files.delete() called on a folder without try-catch. All descendant files owned by the user are permanently deleted in a single operation. There is no confirmation, no progress event, and no partial failure indication — either all owned files are deleted or the call fails entirely.
    ThrowsGaxiosError with status 4xx/5xx if the folder itself cannot be deleted, but descendant deletion is atomic and irreversible on success
    Required handlingWrap in try-catch. Before deleting a folder, enumerate its contents with drive.files.list() to confirm the scope of deletion. For batch cleanup jobs, prefer moving to trash first (files.update with trashed=true) to allow a recovery window, then permanent delete after confirmation.
    costhighin prodimmediate exceptionusers seelost transactionvisibilitysilent
    Sources[8]
  • files.export · drive-files-export-no-try-catch
    error
    Whendrive.files.export() called without try-catch. The exported file may exceed 10 MB (returns 403 with fileNotExportable), the MIME type may be unsupported for the document type, or the user may lack read access to the file.
    ThrowsGaxiosError with status 403 (reason: 'fileNotExportable') for size/format violations, or 404 (reason: 'notFound') for missing files
    Required handlingWrap in try-catch. For 403 with reason === 'fileNotExportable', the document is too large (>10 MB) or the requested MIME type is unsupported for the document type — do NOT retry with the same parameters. For large documents, use the Google Workspace export API with pagination or split the document before export. Always validate the mimeType parameter against the supported export formats for the source document type.
    costmediumin prodimmediate exceptionusers seelost transactionvisibilitysilent
    Sources[4][9]
  • events.delete · calendar-events-delete-no-try-catch
    error
    Whencalendar.events.delete() called without try-catch. The event may not exist (404 notFound), the caller may lack writer access to the calendar (403 forbiddenForNonOrganizer for shared events), or rate limits may be exceeded (403 rateLimitExceeded / userRateLimitExceeded).
    ThrowsGaxiosError with status 404 (reason: 'notFound'), 403 (reason: 'rateLimitExceeded' or 'forbiddenForNonOrganizer')
    Required handlingWrap in try-catch. For 404 errors, the event was already deleted — treat as idempotent success for cleanup jobs. For 403 with reason === 'forbiddenForNonOrganizer', the caller is not the event organizer and the calendar owner has restricted modifications to organizers only. For 403 rate limit errors, implement exponential backoff per the Calendar API quota documentation (60 writes per user per minute).
    costmediumin prodimmediate exceptionusers seelost transactionvisibilitysilent
    Sources[5]
  • values.append · sheets-values-append-no-try-catch
    error
    Whensheets.spreadsheets.values.append() called without try-catch in a high-frequency write path (logging, event streaming, bulk data import). Write quota is 60 requests/user/minute and 300/project/minute. Exceeding quota results in 429 Too Many Requests responses that must be retried with backoff.
    ThrowsGaxiosError with status 429 (rateLimitExceeded) when write quota exceeded; GaxiosError with status 403 (reason: 'insufficientFilePermissions') when caller lacks edit access to the spreadsheet
    Required handlingWrap in try-catch. For 429 errors, implement exponential backoff with jitter (start at 1 second, double each retry, max 32 seconds). For high-volume append jobs, batch multiple rows into a single append call rather than one call per row. For 403 insufficientFilePermissions, the service account or OAuth user lacks editor access to the sheet — do NOT retry until permissions are fixed.
    costmediumin prodimmediate exceptionusers seelost transactionvisibilitysilent
    Sources[6][10]

Sources

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

Official documentation
  • [3]
    developers.google.com/gmail/api/guides
    Handle Errors
  • [4]
    developers.google.com/drive/api/guides
    Handle Errors
  • [5]
    developers.google.com/calendar/api/guides
    Errors
  • [6]
    developers.google.com/sheets/api/limits
    Limits
  • [7]
    developers.google.com/gmail/api/guides
    Push
  • [8]
    developers.google.com/drive/api/reference
    Delete
  • [9]
    developers.google.com/drive/api/reference
    Export
  • [10]
    developers.google.com/sheets/api/reference
    Append
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 — googleapis

Documentation Fetched (2026-04-02)

URLSummary
https://raw.githubusercontent.com/googleapis/google-api-nodejs-client/main/README.mdMain README. Shows error handling with callbacks and promises. Notes that refresh tokens may stop working.
https://raw.githubusercontent.com/googleapis/gaxios/main/README.mdgaxios HTTP client README. Confirms GaxiosError is used for shouldRetry/onRetryAttempt callbacks.
https://raw.githubusercontent.com/googleapis/gaxios/main/src/common.tsGaxiosError class source. Has .status, .code, .response, .config properties. Extends Error.
https://github.com/advisories?query=googleapisGitHub advisories. One historical CVE (GHSA-7543-mr7h-6v86) fixed in v39.1.0, not relevant at v171.

Key Reference Implementations

  • google/claspsrc/core/utils.ts: Definitive handleApiError(error: unknown) that checks instanceof GaxiosError and extracts .status and .errors[0].message.
  • civitai/civitaisrc/server/youtube/client.ts: Callback pattern rejecting with GaxiosError.
  • gitroomhq/postiz-app — Multiple googleapis calls, mix of protected and unprotected.

Error Type

GaxiosError from googleapis-common / gaxios package. Properties:

  • .status — HTTP status code (401, 403, 404, 429, 500...)
  • .response — full HTTP response
  • .response.data — Google API error body
  • .message — human-readable message
Need a different package?
Request a profile