Skip to content

fix(billing): stop the false unbilled-charge error on zero-cost runs - #6333

Merged
waleedlatif1 merged 1 commit into
stagingfrom
fix/usage-ledger-false-unbilled-error
Aug 6, 2026
Merged

fix(billing): stop the false unbilled-charge error on zero-cost runs#6333
waleedlatif1 merged 1 commit into
stagingfrom
fix/usage-ledger-false-unbilled-error

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Problem

Every usage-gated (blocked) execution emitted an ERROR-level log:

Failed to record execution usage to usage_log ledger; charge may be unbilled

This is a 100% false positive on that path. It claims possible revenue loss on runs that never executed and have zero cost — exactly the line an engineer pages on. It misdirected a production investigation for hours. Across 5 days / 683 occurrences, sum(totalCost) = 0 and max(totalCost) = 0.

Mechanism (verified)

  1. apps/sim/lib/execution/preprocessing.ts logPreprocessingError calls session.safeCompleteWithError({ skipCost: true }) and passes no billingAttribution.
  2. skipCost: true makes logging-session.ts build an all-zero costSummary (no base charge, no models, no charges).
  3. logger.ts recordExecutionUsage required a billing context before building targets[]:
    if (workflowRecord.workspaceId && !billingContext) {
      throw new Error('Billing attribution is required for workspace execution usage')
    }
    The throw was caught by the surrounding catch, which logs the unbilled-charge ERROR — even though targets[] would have been empty and recordUsage would never have been called.

Fix

Move the existing if (targets.length === 0) return 0 early return above the attribution requirement. Pure reordering — no new predicate.

No charge can be lost by this change. When targets.length === 0 there is nothing to insert into usage_log: both the old path (throw → catch → log → return 0) and the new path (return 0) record exactly zero. The only difference is the spurious ERROR. Every path with a non-zero target still requires billingContext and still throws when it is missing.

Genuine under-billing still alerts

The ERROR log is not silenced. Any real ledger failure — a recordUsage insert failure, a transaction/advisory-lock failure, or missing billing attribution on a run that does have cost — still reaches the same catch and still logs at ERROR with the full costSummary. Alerting on this line remains valid; it is now specific.

Tests

  • a structurally zero-cost run without billing context logs no unbilled-charge errorfails without the fix (1 spurious ERROR call).
  • a genuine ledger write failure still logs the unbilled-charge error — regression guard; fails if anyone downgrades or removes the ERROR (verified by temporarily switching it to warn).

The file's @sim/logger mock is overridden locally so withMetadata() children share one spy set, making log level assertable.

Verification

  • bunx vitest run lib/logs/execution/logger.test.ts lib/logs/execution/logging-session.test.ts — 98 passed
  • bunx tsc --noEmit -p apps/sim/tsconfig.json — clean
  • bun run lint — clean

recordExecutionUsage required a billing context before it knew whether
there was anything to bill, so a usage-gated run (skipCost, no
billingContext) threw and logged 'charge may be unbilled' for a run that
never executed and had no cost. Move the no-billable-target early return
above the attribution requirement: a genuine ledger write failure still
logs at ERROR.
@vercel

vercel Bot commented Aug 6, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Aug 6, 2026 6:48pm

Request Review

@cursor

cursor Bot commented Aug 6, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Pure reordering of guards in usage recording with no change to ledger writes when cost exists; billing attribution is still enforced before any insert when targets are non-empty.

Overview
Zero-cost workspace completions (e.g. usage-gated runs that never executed, with skipCost: true and no billing attribution) no longer hit the workspace billing-attribution throw and therefore no longer emit the ERROR Failed to record execution usage to usage_log ledger; charge may be unbilled.

In recordExecutionUsage, the existing targets.length === 0 early return is now evaluated before requiring billingContext for workspace workflows. Runs with nothing to ledger still return 0 and skip recordUsage; runs with billable targets still require attribution and still throw when it is missing, so real under-billing paths still reach the same catch and ERROR log.

Tests add a shared @sim/logger mock so ERROR calls are assertable, plus cases for zero-cost-without-context (no spurious ERROR) and genuine recordUsage failures (ERROR still logged).

Reviewed by Cursor Bugbot for commit 5235a4d. Configure here.

@greptile-apps

greptile-apps Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR prevents zero-target executions from emitting a false unbilled-charge error while preserving attribution validation and ledger error reporting whenever a billable target exists.

  • Moves the empty-target return ahead of billing-context resolution.
  • Adds regression coverage for zero-cost completions and genuine ledger-write failures.

Confidence Score: 5/5

The PR appears safe to merge because the new early return applies only when this path has no ledger entries to record.

Nonzero workflow-owned costs still require billing attribution and retain the existing ledger-write and error-reporting flow, while externally owned Mothership costs continue through their separate attributed ledger path.

Important Files Changed

Filename Overview
apps/sim/lib/logs/execution/logger.ts Reorders the existing empty-target return so no-charge executions bypass irrelevant billing-attribution validation without changing nonzero ledger writes.
apps/sim/lib/logs/execution/logger.test.ts Adds shared logger spies and verifies both suppression of the false error and retention of error-level reporting for actual ledger failures.

Reviews (1): Last reviewed commit: "fix(billing): stop the false unbilled-ch..." | Re-trigger Greptile

@waleedlatif1
waleedlatif1 merged commit eb245ad into staging Aug 6, 2026
5 checks passed
@waleedlatif1
waleedlatif1 deleted the fix/usage-ledger-false-unbilled-error branch August 6, 2026 19:02
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.

1 participant