Skip to content

Nullable fields in AccessToken cause runtime crash#144

Closed
PhuCG wants to merge 1 commit intoline:masterfrom
PhuCG:fix/nullable-access-token-fields
Closed

Nullable fields in AccessToken cause runtime crash#144
PhuCG wants to merge 1 commit intoline:masterfrom
PhuCG:fix/nullable-access-token-fields

Conversation

@PhuCG
Copy link
Copy Markdown

@PhuCG PhuCG commented Apr 3, 2026

Problem

AccessToken getters declared non-nullable return types (String, num, List<String>), but values come from a raw Map<String, dynamic>. If any key is missing or null in the server response, Dart throws a runtime exception when casting null to a non-nullable type.

Crash stack trace:

Null check operator used on a null value
#0  AccessToken.tokenType (package:flutter_line_sdk/src/model/access_token.dart:99:32)

Root Cause

// Before — crashes if 'token_type' key is absent
String get tokenType => _data['token_type'];

_data['token_type'] returns dynamic. At runtime, Dart implicitly casts it to String. If the value is null, it throws immediately.

Fix

Changed affected getters to return nullable types:

Getter Before After
value String String?
expiresIn num num?
scopes List<String> List<String>?
tokenType String String?
// After — safe
String? get tokenType => _data['token_type'];
List<String>? get scopes => (_data['scope'] as String?)?.split(' ');

Changes

  • lib/src/model/access_token.dart — updated getter return types
  • test/flutter_line_sdk_test.dart — updated assertions to use null-aware operators

…n, scopes, and tokenType; adjust tests accordingly.
Copy link
Copy Markdown
Member

@onevcat onevcat left a comment

Choose a reason for hiding this comment

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

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

  1. Keep scopes nullableList<String>? is correct since scope may genuinely be absent.
  2. Keep value, expiresIn, tokenType non-nullable — These are required for a valid access token.
  3. Fix the scopes getter with the null-safe chain (as you already did).
  4. 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.

Copy link
Copy Markdown
Member

@onevcat onevcat left a comment

Choose a reason for hiding this comment

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

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!

@onevcat
Copy link
Copy Markdown
Member

onevcat commented Apr 6, 2026

Thanks for reporting this! We've addressed the scopes crash in #145 with a targeted fix that keeps the public API unchanged.

@onevcat onevcat closed this Apr 6, 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.

2 participants