Skip to content

fix(badges): make the unavailable-campaign warning readable in Sentry - #2647

Merged
Hugo0 merged 1 commit into
mainfrom
fix/badge-campaign-warn-payload
Aug 8, 2026
Merged

fix(badges): make the unavailable-campaign warning readable in Sentry#2647
Hugo0 merged 1 commit into
mainfrom
fix/badge-campaign-warn-payload

Conversation

@Hugo0

@Hugo0 Hugo0 commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

The problem

PEANUT-UI-SHW — "Campaign unavailable during registration" — has fired for 2 users since the badge platform release. The Sentry event body is:

arguments: ["Campaign unavailable during registration", ["[Object]"]]

Sentry's console integration serializes each console argument. The second argument was an array of objects, which serializes to the literal "[Object]". So the warning carries neither of the two facts it exists to report: which campaign and why.

The behaviour itself is correct — this is the expected path when someone registers with a link to one of the four campaigns retired in the release, and registration still completes. But as shipped the warning is unactionable: you cannot tell a retired campaign from a genuinely broken active one.

The fix

Pre-join the pairs into a single string:

unavailable.map(({ badgeCampaign, outcome }) => `${badgeCampaign}=${outcome}`).join(', ')

The Sentry event now reads "irl-nomads=inactive, ethfloripa=unknown".

The message stays constant on purpose. Interpolating campaign names into the message string would have been the obvious fix, but Sentry groups console issues by message — that would open a new issue per campaign combination and fragment a single low-volume warning into many. Keeping the message fixed and putting the detail in the argument gets readable data and stable grouping.

Test

Added to useZeroDev-invite-onboarding.test.tsx. It asserts the payload is a string, that it names both campaigns and both reasons, and that the message is unchanged (the grouping guard).

Verified non-vacuous — reinstating the object array fails the test, restoring the join passes:

✕ names the unavailable campaign and reason in a form Sentry can read   <- with the bug
✓ names the unavailable campaign and reason in a form Sentry can read   <- with the fix

Verification

  • tsc --noEmit clean
  • prettier — both files already conformant
  • full suite: 225 suites, 2884 passed, 3 skipped, 0 failed

Risk

None to behaviour. This changes only what gets written to the console/Sentry on an already-correct branch. No control flow, no user-visible surface.

Follow-up to the badge platform release (#2613), found in the post-release Sentry sweep.

Summary by CodeRabbit

  • Bug Fixes
    • Improved registration warning details for unavailable badge campaigns, making campaign names and outcome reasons easier to read in monitoring tools.
    • Preserved the existing warning message and behavior.

The warning logged an array of objects as its second console argument.
Sentry's console integration serializes each argument, and an array of
objects lands in the issue as the literal "[Object]" — so the two facts the
warning exists to carry, which campaign and why, were both unreadable in
production. Two users hit it since the badge release and neither event says
which campaign failed.

Pre-join the pairs into one string. The message itself stays constant so
Sentry keeps grouping these into a single issue rather than opening one per
campaign combination.

Test asserts the payload is a string, names both campaigns and reasons, and
pins the message constant. Verified non-vacuous: reinstating the object array
fails it, restoring the join passes.
@cursor

cursor Bot commented Aug 8, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@vercel

vercel Bot commented Aug 8, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
peanut-wallet Ready Ready Preview Aug 8, 2026 9:05am

Request Review

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: df548434-6640-4e3b-ae6b-06dcc527c1df

📥 Commits

Reviewing files that changed from the base of the PR and between 89e5664 and c970558.

📒 Files selected for processing (2)
  • src/hooks/__tests__/useZeroDev-invite-onboarding.test.tsx
  • src/hooks/useZeroDev.ts

📝 Walkthrough

Walkthrough

The registration warning for unavailable badge campaigns now uses readable campaign=outcome pairs. A regression test verifies multiple campaigns, the constant warning message, and the Sentry-readable string format.

Changes

Campaign warning output

Layer / File(s) Summary
Warning formatting and regression coverage
src/hooks/useZeroDev.ts, src/hooks/__tests__/useZeroDev-invite-onboarding.test.tsx
The warning serializes unavailable campaigns as readable campaign=outcome pairs. The registration test verifies multiple entries and preserves the warning message.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested reviewers: 0xkkonrad

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: making unavailable-campaign warnings readable in Sentry.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/badge-campaign-warn-payload

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Code-analysis diff

Painscore total: 7133.95 → 7134.13 (+0.18)
Findings: 0 net (+7 new, -7 resolved)

🆕 New findings (7)

  • high hotspot — src/hooks/useZeroDev.ts — 38 commits, +404/-232 lines since 6 months ago
  • medium high-mdd — src/hooks/useZeroDev.ts:57 — useZeroDev: MDD 67.1 (uses across many lines from declarations)
  • medium high-dlt — src/hooks/useZeroDev.ts:57 — useZeroDev: DLT 62 (calls 62 distinct functions — high context load)
  • medium high-dlt — src/hooks/useZeroDev.ts:69 — handleRegister: DLT 37 (calls 37 distinct functions — high context load)
  • medium high-mdd — src/hooks/useZeroDev.ts:69 — handleRegister: MDD 31.7 (uses across many lines from declarations)
  • low high-mdd — src/hooks/useZeroDev.ts:299 — : MDD 18.6 (uses across many lines from declarations)
  • low high-dlt — src/hooks/useZeroDev.ts:299 — : DLT 17 (calls 17 distinct functions — high context load)

✅ Resolved (7)

  • src/hooks/useZeroDev.ts — 37 commits, +396/-231 lines since 6 months ago
  • src/hooks/useZeroDev.ts:57 — useZeroDev: MDD 65.3 (uses across many lines from declarations)
  • src/hooks/useZeroDev.ts:57 — useZeroDev: DLT 61 (calls 61 distinct functions — high context load)
  • src/hooks/useZeroDev.ts:69 — handleRegister: DLT 36 (calls 36 distinct functions — high context load)
  • src/hooks/useZeroDev.ts:69 — handleRegister: MDD 30.6 (uses across many lines from declarations)
  • src/hooks/useZeroDev.ts:292 — : MDD 18.6 (uses across many lines from declarations)
  • src/hooks/useZeroDev.ts:292 — : DLT 17 (calls 17 distinct functions — high context load)

@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

🧪 UI test report — ✅ all green

Suites

  • unit: 2887 ran, 0 failed, 0 skipped, 50.5s

📊 Coverage (unit)

metric %
statements 66.0%
branches 50.9%
functions 56.0%
lines 66.7%
⏱ 10 slowest test cases
time test
3.6s src/components/Card/share-asset/__tests__/shareAssetLayout.test.ts › never places two stickers in heavy overlap (broad seed sweep)
1.2s src/utils/__tests__/demo-api.test.ts › isDemoMode() is false when not running under Capacitor
0.3s src/utils/__tests__/sentry.utils.test.ts › defaults to the client budget under a browser global
0.3s src/app/(mobile-ui)/withdraw/__tests__/withdraw-states.test.tsx › Bank withdrawal keeps the $1 minimum for sub-$1 amounts
0.3s src/components/Card/share-asset/__tests__/shareAssetLayout.test.ts › every sticker stays within canvas at any count
0.3s src/utils/__tests__/auth-token.test.ts › authReady does not park — hydrates the plain token without an unlock
0.3s src/utils/__tests__/sentry.utils.test.ts › still lets a per-call timeoutMs win over the default
0.3s src/utils/__tests__/auth-token.test.ts › is none — never guarded — when only the guarded marker is present
0.3s src/app/actions/__tests__/api-headers.test.ts › should include Content-Type in validateInviteCode
0.3s src/utils/__tests__/auth-token.test.ts › returns the token hydrated from Preferences after authReady
📍 Inline annotations are in the **Unit test report** check above. Coverage artifact: `coverage-unit`. Generated by `.github/workflows/tests.yml`.

@Hugo0
Hugo0 merged commit 3b80afb into main Aug 8, 2026
26 checks passed
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