Skip to content

[BUG] Sentry crash reporting opt-out is not respected #397

Description

@gurgle-mandolin

AI Disclosure: I used Claude Opus 5 when writing this bug report. I (a human) reviewed and edited the output.

Line numbers below refer to main at commit c9bef19.

Summary

The "Sentry crash-reporting opt-out" setting added in #211 appears to not be respected after an app restart.

main() reads settings.trackErrors synchronously, immediately after constructing Settings():

// lib/main.dart:23-24
var settings = Settings();
if (settings.trackErrors && !kDebugMode) {

But Settings._internal() loads config.json asynchronously:

// lib/services/settings.dart:83-97
static final Settings _instance = Settings._internal();

factory Settings() {
  return _instance;
}

Settings._internal() {
  _storage.readFile("config.json").then((rawConfig) {   // completes later
    if (rawConfig != null) {
      _settings = jsonDecode(rawConfig);
    }

    _change.add(null);
  });
}

So when main() reads settings.trackErrors, _settings is still empty and the getter falls back to its default:

// lib/services/settings.dart:10, 45-47
bool defaultTrackErrors = true;

bool get trackErrors {
  return _getBool('trackErrors', defaultTrackErrors);
}
// lib/services/settings.dart:58-64
bool _getBool(String key, bool defaultValue) {
  final val = _settings[key];
  if (val is bool) {
    return val;
  }
  return defaultValue; 
}

A user who turns off "Report errors automatically" therefore gets Sentry re-enabled on every subsequent launch, despite the setting being correctly displayed in the UI.

Reproduction

test/models/settings_test.dart (attached) reproduces this without a device. It writes a config.json containing {"trackErrors": false, "logWrap": true}, points path_provider at that directory, and reads settings the way main() does.

$ flutter test test/models/settings_test.dart

00:00 +0 -1: settings read immediately after construction reflect config.json [E]
  Expected: false
    Actual: <true>
  user disabled error tracking in config.json

The second test in that file is identical except that it waits for the async load, and it passes.

settings_test.dart (uploaded as a .txt because github won't let me upload a .dart file)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions