Skip to content

Conversation

@grdsdev
Copy link
Contributor

@grdsdev grdsdev commented Jan 23, 2026

Summary

Improve JSON parsing resilience across all Supabase Flutter SDK packages with explicit type validation and robust error handling. Support both int and num numeric types to handle different JSON decoder behaviors. Add unknown enum values for forward compatibility.

Changes

  • Add explicit type casts (as String, as Map<String, dynamic>) for all JSON fields
  • Change numeric type checks from is! int to is! num with .toInt() conversion
  • Add comprehensive validation for required fields with clear FormatException messages
  • Add unknown enum values to FactorType and FactorStatus for forward compatibility
  • Fix input map mutation in Presence.fromJson and PostgresChangePayload.fromPayload

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Improved error handling and validation across auth, session, MFA, realtime, storage, and PostgREST flows to avoid crashes on malformed or unexpected server responses.
    • MFA parsing hardened and now tolerates unknown factor types/statuses to prevent runtime failures.
  • Refactor

    • Safer deserialization and construction for sessions, presence, storage objects, change payloads, and token-refresh disposal for more predictable behavior.
  • Chores

    • Removed an unused macOS plugin registration.

✏️ Tip: You can customize this high-level summary in your review settings.

Add explicit type casts and validation for JSON parsing across all SDK
packages. Support both int and num numeric types for better compatibility
with different JSON decoders. Add unknown enum values for forward
compatibility with new factor types and statuses.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
@coderabbitai
Copy link

coderabbitai bot commented Jan 23, 2026

📝 Walkthrough

Walkthrough

Replace force-unwrapping with factories/private parsers across packages, add runtime type and numeric/date validations, introduce unknown enum variants, and tighten error handling by throwing FormatException. No public API removals or signature downgrades.

Changes

Cohort / File(s) Summary
Auth response parsing
packages/gotrue/lib/src/types/auth_response.dart
Replace force-unwrapped User.fromJson(json) with private _parseUser that validates and throws FormatException on failure.
Gotrue client dispose
packages/gotrue/lib/src/gotrue_client.dart
Guard token-refresh completer completion with null and isCompleted checks before completing with AuthException('Disposed').
MFA deserialization
packages/gotrue/lib/src/types/mfa.dart
Add FactorType.unknown and FactorStatus.unknown; explicit casts for ids/strings; numeric validation for expires fields; parseDateTime helper; stricter mapping/type checks across MFA responses.
Session parsing
packages/gotrue/lib/src/types/session.dart
Validate user is a Map<String, dynamic>, parse into local user via User.fromJson, and throw FormatException on invalid input.
Postgrest response validation
packages/postgrest/lib/src/types.dart
Validate count is numeric, convert with toInt(), and throw FormatException if invalid in PostgrestResponse.fromJson.
Realtime presence
packages/realtime_client/lib/src/realtime_presence.dart
Add const named constructor for Presence; convert Presence.fromJson to a factory extracting presence_ref, defaulting missing values, and avoiding input mutation.
Realtime types (change payload)
packages/realtime_client/lib/src/types.dart
Convert PostgresChangePayload.fromPayload to a factory; safe parsing for commit_timestamp (fallback epoch), enforce map types for new/old records, and add timestamp parsing error handling.
Storage client types
packages/storage_client/lib/src/types.dart
Convert Bucket.fromJson, FileObject.fromJson, and FileObjectV2.fromJson to factory constructors; add runtime type checks, normalize owner, validate allowed_mime_types, and throw FormatException on invalid inputs.
Example plugin cleanup
packages/supabase_flutter/example/macos/.../GeneratedPluginRegistrant.swift
Removed path_provider_foundation import and its registration call.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

I nibble lines and mend each field,
Guarding types so nothing yields.
Unknowns tucked in gentle rows,
Errors caught before they grow.
A rabbit's hop—safe JSON flows. 🐇✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(types): improve JSON decoding resilience' directly and accurately summarizes the main change: enhancing JSON parsing robustness across multiple type definitions in the SDK.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@grdsdev grdsdev requested a review from a team January 23, 2026 11:03
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@packages/gotrue/lib/src/types/session.dart`:
- Around line 34-46: The FormatException constructors in the session parsing
(the userJson check and the User.fromJson null branch) currently include
json.toString(), which can leak tokens/PII; update these throws to omit the full
payload or supply a redacted summary instead (e.g., no second argument or a
small redacted map/string), altering the two places that construct
FormatException around userJson and User.fromJson to avoid embedding the
original json contents.
🧹 Nitpick comments (1)
packages/realtime_client/lib/src/realtime_presence.dart (1)

18-26: Good implementation that correctly avoids input mutation.

The shallow copy with Map<String, dynamic>.from(map) before removing 'presence_ref' properly addresses the mutation concern mentioned in the PR objectives. The null-coalescing to empty string provides sensible resilient decoding.

Minor note: In deepClone() (line 30-31), if payload somehow contains a 'presence_ref' key, it would shadow the explicit assignment due to spread order. This is unlikely given fromJson removes it, but you could swap the order for defensive coding:

return Presence.fromJson({
  ...payload,
  'presence_ref': presenceRef,  // Ensure this takes precedence
});

grdsdev and others added 2 commits January 23, 2026 08:28
Avoid leaking tokens and PII by removing json.toString() from
FormatException constructors in Session.fromJson.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Check if the completer is already completed before calling completeError
in dispose() to avoid "Bad state: Future already completed" errors during
concurrent dispose operations.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
@coveralls
Copy link

Pull Request Test Coverage Report for Build 21360896419

Warning: This coverage report may be inaccurate.

This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.

Details

  • 96 of 157 (61.15%) changed or added relevant lines in 8 files are covered.
  • 2 unchanged lines in 2 files lost coverage.
  • Overall coverage decreased (-0.7%) to 79.627%

Changes Missing Coverage Covered Lines Changed/Added Lines %
packages/gotrue/lib/src/types/auth_response.dart 3 5 60.0%
packages/storage_client/lib/src/types.dart 40 42 95.24%
packages/gotrue/lib/src/gotrue_client.dart 0 3 0.0%
packages/gotrue/lib/src/types/session.dart 3 6 50.0%
packages/realtime_client/lib/src/realtime_presence.dart 0 5 0.0%
packages/realtime_client/lib/src/types.dart 14 19 73.68%
packages/postgrest/lib/src/types.dart 0 9 0.0%
packages/gotrue/lib/src/types/mfa.dart 36 68 52.94%
Files with Coverage Reduction New Missed Lines %
packages/gotrue/lib/src/gotrue_client.dart 1 63.85%
packages/gotrue/lib/src/types/mfa.dart 1 65.22%
Totals Coverage Status
Change from base Build 21250088460: -0.7%
Covered Lines: 3416
Relevant Lines: 4290

💛 - Coveralls

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.

4 participants