Skip to content

Conversation

@aadamgough
Copy link
Contributor

Summary

Added better error handling for vault specifically. Google Cloud by default has a limit for token expiration, and they throw invalid_grant after the token expires, and the only workaround to this is disconneting and reconnecting credential, or, as an admin, disabling reauth for Sim.

Also added additional params for dates

Type of Change

  • Bug fix
  • New feature

Testing

Tested manually. Don't merge yet (will remove this once the token has manually expired after an hour)

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel
Copy link

vercel bot commented Jan 8, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Review Updated (UTC)
docs Skipped Skipped Jan 8, 2026 11:20pm

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Greptile Overview

Greptile Summary

This PR improves error handling for OAuth token refresh failures and adds date filtering capabilities to Google Vault tools.

Major Changes:

  • Enhanced error messages for Google Workspace session control (invalid_rapt) and revoked credentials (invalid_grant)
  • Added date filtering (startTime, endTime) and search terms to Google Vault export and hold operations
  • Propagates detailed error messages from OAuth refresh failures to end users

Critical Issues Found:

  • Breaking Change: getOAuthToken and refreshAccessTokenIfNeeded in utils.ts now throw errors instead of returning null, but 30+ existing callers expect null and use if (!accessToken) checks. This will cause unhandled exceptions in webhook services, cron jobs, and API routes.
  • Missing null checks in oauth.ts when using typeof errorData === 'object' (which is true for null in JavaScript)

Google Vault Improvements:

  • Successfully adds date/time filtering for exports and holds
  • Properly handles corpus-specific query construction (MAIL/GROUPS for date filtering, DRIVE for shared drives)
  • Removed unused timeZone parameter
  • Minor UX issue: Date filtering fields show for all corpus types even though holds only support them for MAIL and GROUPS

Confidence Score: 1/5

  • This PR contains a critical breaking change that will cause runtime errors across the application
  • The change from returning null to throwing errors in getOAuthToken and refreshAccessTokenIfNeeded breaks backward compatibility with 30+ callers that expect null checks. This will cause unhandled promise rejections in production, affecting webhooks, cron jobs, and API endpoints. The improved error messages are good, but the implementation breaks existing code.
  • apps/sim/app/api/auth/oauth/utils.ts requires immediate attention - the error handling changes will break multiple services. apps/sim/lib/oauth/oauth.ts needs null safety fixes for typeof checks.

Important Files Changed

File Analysis

Filename Score Overview
apps/sim/app/api/auth/oauth/token/route.ts 3/5 Improved error message propagation from token refresh failures, now surfaces specific error details to users
apps/sim/app/api/auth/oauth/utils.ts 1/5 CRITICAL: Changed error handling from returning null to throwing errors, breaking backward compatibility with 30+ callers expecting null checks
apps/sim/lib/oauth/oauth.ts 2/5 Added specific error messages for Google Workspace session control and invalid_grant errors; null check missing in typeof checks
apps/sim/blocks/blocks/google_vault.ts 4/5 Added date filtering and search terms for exports/holds with AI-assisted input generation; minor issue with corpus-specific field visibility

Sequence Diagram

sequenceDiagram
    participant Client
    participant API as OAuth API Route
    participant Utils as OAuth Utils
    participant Lib as OAuth Library
    participant Provider as Google OAuth

    Client->>API: Request access credentials
    API->>Utils: getOAuthToken or refreshAccessTokenIfNeeded
    Utils->>Lib: refreshOAuthToken with provider details
    Lib->>Provider: POST refresh request
    
    alt Session Control Error (RAPT)
        Provider-->>Lib: Error response with invalid_rapt subtype
        Lib-->>Utils: throw Error with reconnect instructions
        Utils-->>API: propagate error
        API-->>Client: 401 or 403 with user-friendly message
    else General Invalid Grant
        Provider-->>Lib: Error response with invalid_grant
        Lib-->>Utils: throw Error requesting reconnection
        Utils-->>API: propagate error
        API-->>Client: 401 or 403 with reconnect message
    else Success
        Provider-->>Lib: New credentials with expiry
        Lib-->>Utils: Return refreshed credentials
        Utils->>Utils: Update database
        Utils-->>API: Return valid credentials
        API-->>Client: Success response
    end

    Note over Utils: BREAKING CHANGE in utils.ts<br/>Changed from returning null to throwing errors
    Note over API: Most callers expect null checks<br/>Will crash without try-catch blocks
Loading

Comment on lines 257 to 267
} catch (error) {
// Re-throw the error to propagate detailed error messages (e.g., session expiry instructions)
logger.error(`[${requestId}] Error refreshing token for credential`, {
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined,
providerId: credential.providerId,
credentialId,
userId: credential.userId,
})
return null
throw error
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing return null to throw error breaks backward compatibility. Many callers expect refreshAccessTokenIfNeeded to return null on failure and check if (!accessToken). This change will cause unhandled exceptions in:

  • apps/sim/lib/webhooks/utils.server.ts:2129,2816,2902
  • apps/sim/lib/webhooks/provider-subscriptions.ts:57,190
  • apps/sim/app/api/tools/gmail/labels/route.ts:70
  • apps/sim/app/api/tools/sharepoint/sites/route.ts:53
  • Plus 20+ more files

Either revert to returning null, or wrap all callers in try-catch blocks.

Comment on lines +1197 to +1200
if (
typeof errorData === 'object' &&
(errorData.error_subtype === 'invalid_rapt' ||
errorData.error_description?.includes('reauth related error'))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typeof errorData === 'object' is true for null in JavaScript. Should add && errorData !== null to prevent null pointer exceptions when accessing errorData.error_subtype

Suggested change
if (
typeof errorData === 'object' &&
(errorData.error_subtype === 'invalid_rapt' ||
errorData.error_description?.includes('reauth related error'))
if (
typeof errorData === 'object' &&
errorData !== null &&
(errorData.error_subtype === 'invalid_rapt' ||
errorData.error_description?.includes('reauth related error'))

Comment on lines +1207 to +1210
if (
typeof errorData === 'object' &&
errorData.error === 'invalid_grant' &&
!errorData.error_subtype
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typeof errorData === 'object' is true for null in JavaScript. Should add && errorData !== null

Suggested change
if (
typeof errorData === 'object' &&
errorData.error === 'invalid_grant' &&
!errorData.error_subtype
if (
typeof errorData === 'object' &&
errorData !== null &&
errorData.error === 'invalid_grant' &&
!errorData.error_subtype

Comment on lines +162 to +169
// Date filtering for exports and holds (holds only support MAIL and GROUPS corpus)
{
id: 'startTime',
title: 'Start Time',
type: 'short-input',
placeholder: 'YYYY-MM-DDTHH:mm:ssZ',
condition: { field: 'operation', value: ['create_matters_export', 'create_matters_holds'] },
wandConfig: {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Date filtering fields show for all corpus types, but the comment states "holds only support MAIL and GROUPS corpus" for date filtering. Consider adding corpus-based conditions:

Suggested change
// Date filtering for exports and holds (holds only support MAIL and GROUPS corpus)
{
id: 'startTime',
title: 'Start Time',
type: 'short-input',
placeholder: 'YYYY-MM-DDTHH:mm:ssZ',
condition: { field: 'operation', value: ['create_matters_export', 'create_matters_holds'] },
wandConfig: {
{
id: 'startTime',
title: 'Start Time',
type: 'short-input',
placeholder: 'YYYY-MM-DDTHH:mm:ssZ',
condition: {
field: 'operation',
value: ['create_matters_export', 'create_matters_holds']
},

Or if holds truly need corpus restriction, the condition should be more complex to check corpus for holds operations.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Jan 8, 2026

Additional Comments (1)

apps/sim/app/api/auth/oauth/utils.ts
Changing return null to throw error breaks backward compatibility. Many callers expect getOAuthToken to return null on failure and check if (!accessToken). This change will cause unhandled exceptions throughout the codebase in:

  • apps/sim/lib/webhooks/gmail-polling-service.ts:171
  • apps/sim/lib/webhooks/outlook-polling-service.ts:217
  • apps/sim/app/api/webhooks/route.ts:838,1082
  • apps/sim/app/api/auth/oauth/token/route.ts:75

Either revert to returning null, or wrap all callers in try-catch blocks.

@aadamgough aadamgough closed this Jan 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants