From 9c2a46a63f86e33d173d77af33edd72855f1c465 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Sun, 23 Aug 2026 18:57:39 -0700 Subject: [PATCH] fix: surface an unbilled run, and clamp the google-docs page cap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two places where a failure is reported as something smaller than it is. **A run that is never billed logs as a notification problem.** The usage safety net re-records billing when an earlier step threw before the single record call, and its own failure went into a bare `catch {}`. With a degraded database the user lookup throws first, the re-record hits the same database and is swallowed, and the only line emitted reads "Usage threshold notification check failed (non-fatal)" — which is true of the outer failure and badly wrong about the inner one. It now logs at error with the execution and workflow ids, and says the run may be unbilled. The outer warn still covers the email path it was written for. **google-docs can ask Drive for a negative page.** `remaining` was `maxDocs - previouslyFetched` unclamped, where its google-slides twin carries `Math.max(0, …)` under the comment "Last-page precision". Both then run `if (documents.length > remaining) documents = documents.slice(0, remaining)`, and a negative `remaining` makes that guard true for any non-empty page while `slice` counts from the end — keeping the leading documents and dropping the trailing ones, where the cap says to keep none. Reachable when `maxDocs` is lowered while a sync cursor persists. google-drive guards the same case with an early return; google-docs had neither. --- apps/sim/connectors/google-docs/google-docs.ts | 3 ++- apps/sim/lib/logs/execution/logger.ts | 11 ++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/apps/sim/connectors/google-docs/google-docs.ts b/apps/sim/connectors/google-docs/google-docs.ts index fae56ea5f1a..51114f376e5 100644 --- a/apps/sim/connectors/google-docs/google-docs.ts +++ b/apps/sim/connectors/google-docs/google-docs.ts @@ -304,7 +304,8 @@ export const googleDocsConnector: ConnectorConfig = { const maxDocs = sourceConfig.maxDocs ? Number(sourceConfig.maxDocs) : 0 const previouslyFetched = (syncContext?.totalDocsFetched as number) ?? 0 - const remaining = maxDocs > 0 ? maxDocs - previouslyFetched : 0 + /** Last-page precision: never ask Drive for more files than the cap still allows. */ + const remaining = maxDocs > 0 ? Math.max(0, maxDocs - previouslyFetched) : 0 const pageSize = remaining > 0 ? Math.min(PAGE_SIZE, remaining) : PAGE_SIZE /** diff --git a/apps/sim/lib/logs/execution/logger.ts b/apps/sim/lib/logs/execution/logger.ts index 828cdc27de8..00d04a72b2d 100644 --- a/apps/sim/lib/logs/execution/logger.ts +++ b/apps/sim/lib/logs/execution/logger.ts @@ -1399,7 +1399,16 @@ export class ExecutionLogger implements IExecutionLoggerService { actorUserId, exactBillingContext ) - } catch {} + } catch (recordError) { + /* The safety net is the last thing between a completed run and an unbilled + one. Swallowing it left the only emitted line saying a notification check + had failed and was non-fatal. */ + execLog.error('Failed to record execution usage — this run may be unbilled', { + error: recordError, + executionId, + workflowId: updatedLog.workflowId, + }) + } execLog.warn('Usage threshold notification check failed (non-fatal)', { error: e }) }