Skip to content

fix(vercel): log drains_unavailable provisioning failures at WARN not ERROR #SUPERLOG - #449

Open
superlog-app[bot] wants to merge 1 commit into
mainfrom
superlog/vercel-warn-drains-unavailable
Open

fix(vercel): log drains_unavailable provisioning failures at WARN not ERROR #SUPERLOG#449
superlog-app[bot] wants to merge 1 commit into
mainfrom
superlog/vercel-warn-drains-unavailable

Conversation

@superlog-app

@superlog-app superlog-app Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Every user whose Vercel team plan doesn't include drains (Vercel's log/OTLP drain feature is a paid-plan gate) triggers a production incident via a log.error call in the OAuth callback handler. The provisioning correctly detects and handles this as drains_unavailable — rolling back the configuration, redirecting the user to a clear error page — but then logs at ERROR, which fires Superlog incidents that operators cannot act on.

Root Cause

In apps/api/src/vercel.ts, the provisioning catch block called log.error unconditionally before computing the outcome:

log.error({ err: e, project_id: decoded.projectId }, "vercel provisioning failed");
const outcome = e instanceof VercelProvisioningError ? e.outcome : "error";

When Vercel rejects both POST /v1/drains calls with 403 "Drains are not available for team '...'", classifyDrainProvisioningFailure correctly produces outcome: "drains_unavailable". The per-signal WARN logs already record the Vercel API message. But the catch block's unconditional log.error then fires on top of them, creating the incident.

Telemetry confirmed 7 occurrences across 4 distinct Vercel teams since 2026-07-03, every one carrying outcome: "drains_unavailable"; no outcome: "error" events have ever been observed in production.

Remediation

This PR computes the outcome before logging and downgrades to log.warn when the outcome is drains_unavailable (an expected external API condition), while preserving log.error for unexpected failures.

All 19 Vercel-service unit tests pass. The 75 pre-existing test failures in the repo are unrelated to this change (confirmed by baseline before/after comparison).

Related incident: frosted-quokka (0582f35d-b982-4506-ab89-7501409d9fda)


Was this PR helpful? Leave feedback — goes straight to the Superlog team.


Summary by cubic

Downgrade logging of Vercel drains_unavailable provisioning failures from ERROR to WARN to prevent false Superlog incidents, while keeping unexpected failures as errors.

  • Bug Fixes
    • Compute the provisioning outcome before logging.
    • Log warn for drains_unavailable; keep error for other outcomes.

Written for commit a3da0b8. Summary will update on new commits.

Review in cubic

… ERROR #SUPERLOG

Delivery-Id: 1e749afb902bf4ce7bf34e9359095ed0c49805fe806bf56d6c011acf0d793be9
Delivery-Base: main

@superlog-app superlog-app Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Observability review

  • 1 blocking

Comment thread apps/api/src/vercel.ts
// drains_unavailable is a known Vercel plan restriction — per-signal WARN
// logs already capture the API message; escalating to ERROR creates
// incidents for a condition operators cannot act on.
if (outcome === "drains_unavailable") {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

logs · blocking — Use log.info, not log.warn, for the drains_unavailable branch

Replace log.warn with log.info: drains_unavailable is expected control flow (a Vercel plan gate the operator cannot act on), and the rubric reserves warn for nothing — info is the correct level for expected, non-actionable outcomes. Using warn still risks alert rules that key on severity ≥ warn, defeating the purpose of this fix.

Suggested change
if (outcome === "drains_unavailable") {
log.info({ err: e, project_id: decoded.projectId }, "vercel provisioning failed");

Useful? React with 👍 / 👎.

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