Nullable fields in AccessToken cause runtime crash#144
Nullable fields in AccessToken cause runtime crash#144PhuCG wants to merge 1 commit intoline:masterfrom
Conversation
…n, scopes, and tokenType; adjust tests accordingly.
onevcat
left a comment
There was a problem hiding this comment.
Thanks for reporting this crash and taking the time to investigate! The null safety issue on scopes is a real bug. However, I have concerns about the overall approach of making all four getters nullable. Here's my reasoning:
Core concern: weakening the type contract
AccessToken represents a successfully obtained access token from the LINE Platform. For a valid token, access_token, expires_in, and token_type are required fields in the LINE Login API response. Making them nullable pushes error handling onto every caller — anyone using .value now needs a null check for a case that shouldn't logically happen with a valid token.
This is also a breaking API change for all existing consumers of this package. Every call site that accesses .value, .expiresIn, .scopes, or .tokenType will now require null handling.
The real bug
The actual crash risk is in scopes:
// This crashes if 'scope' is null because you call .split() on null
List<String> get scopes => _data['scope'].split(' ');The scope field can legitimately be absent (e.g., when no specific scopes were requested). Your fix for this one is correct — the null-safe chain (_data['scope'] as String?)?.split(' ') is the right approach.
For the other three fields (value, expiresIn, tokenType), if they're missing from the native SDK response, the token data is malformed and we should fail fast rather than return a half-valid AccessToken that will cause confusing errors later.
Suggested approach
- Keep
scopesnullable —List<String>?is correct sincescopemay genuinely be absent. - Keep
value,expiresIn,tokenTypenon-nullable — These are required for a valid access token. - Fix the
scopesgetter with the null-safe chain (as you already did). - Optionally, add an explicit cast for the other getters to produce a clearer error message:
String get value => _data['access_token'] as String; num get expiresIn => _data['expires_in'] as num; String get tokenType => _data['token_type'] as String;
This way, if native data is somehow malformed, you get a clear TypeError with the actual type mismatch, rather than a vague "Null check operator used on a null value."
Test changes
The test file diff is mostly whitespace reformatting (re-indentation of the switch block). Unrelated formatting changes mixed with functional changes make the diff harder to review. I'd suggest keeping them separate.
Also, if scopes is made nullable, it would be good to add a test case for when scope is absent from the token data.
onevcat
left a comment
There was a problem hiding this comment.
Thanks for the report and the fix for scopes — that's a real bug.
However, for value, expiresIn, and tokenType, our API contract guarantees these fields are always present in a valid access token. Making them nullable would be a breaking change for all consumers without real benefit — if the native SDK somehow returns malformed data, we'd rather fail fast than silently propagate nulls.
We'll address the scopes issue separately with a targeted fix. Thanks again for catching this!
|
Thanks for reporting this! We've addressed the |
Problem
AccessTokengetters declared non-nullable return types (String,num,List<String>), but values come from a rawMap<String, dynamic>. If any key is missing ornullin the server response, Dart throws a runtime exception when castingnullto a non-nullable type.Crash stack trace:
Root Cause
_data['token_type']returnsdynamic. At runtime, Dart implicitly casts it toString. If the value isnull, it throws immediately.Fix
Changed affected getters to return nullable types:
valueStringString?expiresInnumnum?scopesList<String>List<String>?tokenTypeStringString?Changes
lib/src/model/access_token.dart— updated getter return typestest/flutter_line_sdk_test.dart— updated assertions to use null-aware operators