Skip to content

fix(sdk): handle non-JSON success response for streak freeze buy - #1517

Closed
sentry[bot] wants to merge 1 commit into
developfrom
seer/fix/sdk-streak-freeze-json-parse
Closed

fix(sdk): handle non-JSON success response for streak freeze buy#1517
sentry[bot] wants to merge 1 commit into
developfrom
seer/fix/sdk-streak-freeze-json-parse

Conversation

@sentry

@sentry sentry Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

This PR addresses a SyntaxError: JSON.parse: unexpected character that occurred when the /private-api/streak-freeze/buy endpoint returned a successful (2xx) HTTP response with a non-JSON body (e.g., empty or HTML).

Root Cause:
The buyStreakFreezeRequest function in packages/sdk/src/modules/quests/mutations/buy-streak-freeze.ts was calling response.json() directly on the success path without checking the Content-Type header or wrapping it in a try/catch block. This led to an unhandled SyntaxError if the server responded with valid HTTP status but an unexpected body format.

Solution:
Implemented a more robust response parsing mechanism, mirroring the approach already present in use-claim-points.ts:

  1. The response body is now initially read as plain text using response.text().
  2. The Content-Type header is checked. If it does not indicate JSON, a descriptive error ([SDK][StreakFreeze] – expected JSON but received "..." response) is thrown.
  3. If the Content-Type is JSON, JSON.parse() is called within a try/catch block. If parsing fails, a descriptive error ([SDK][StreakFreeze] – malformed JSON response) is thrown.

This ensures that unexpected response formats are handled gracefully, preventing unhandled SyntaxError exceptions and providing clearer error messages for debugging.

Test Updates:

  • Updated existing fetch mocks in buy-streak-freeze.spec.ts to include headers.get() and text() methods, as the new implementation relies on these.
  • Added new test cases to specifically cover scenarios where the API returns a 2xx response with a non-JSON Content-Type or malformed JSON.

Fixes ECENCY-NEXT-1FCJ

This PR was automatically generated by Sentry. You can adjust this setting at any time.

@feruzm

feruzm commented Aug 18, 2026

Copy link
Copy Markdown
Member

Closing: the issue is real but this is not the code that throws it.

ECENCY-NEXT-1FCJ is an unhandled rejection on /perks in all 11 retained events. buy-streak-freeze.ts cannot be its source:

  1. The file landed on 2026-07-06, while 6 of the 11 events predate it (2026-05-22 through 2026-07-02).
  2. Its only call site, handleBuyFreeze in apps/web/src/app/perks/components/perks-quests-section.tsx, already wraps await buyFreeze() in try/catch, so a SyntaxError there could never surface as an unhandled rejection.
  3. No event's breadcrumbs contain a /private-api/streak-freeze/buy request.
  4. The 2026-07-10 event's last breadcrumb before the throw is POST 502 /private-api/post-game, and the 2026-07-26 event ends with clicks on the spin modal's body and footer.

The actual source is game-claim.ts, which calls response.json() with no ok check and no content-type check, reached from an uncaught await claim() in perks-points-spin-banner.tsx. Fixed in #1526, which uses the same content-type guard this PR proposed.

Worth noting the same issue ID was already "fixed" once in use-claim-points.ts on 2026-07-10 and kept firing afterwards, for the same reason: the file was guessed from the pattern rather than from the event trail.

@feruzm feruzm closed this Aug 18, 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.

1 participant