Bug description
When saving a workout log in gym mode, the app crashes with:
Error: Null check operator used on a null value
#0 State.setState (package:flutter/src/widgets/framework.dart:1219)
#1 _LogFormWidgetState.build.<anonymous closure> (log_page.dart:653)
The log is saved correctly on the server (POST /api/v2/workoutlog/ returns 201), but the crash makes the user think it failed. On retry, duplicate log entries are created.
Steps to reproduce
- Open a routine in gym mode
- Enter reps/weight and tap Save
- App crashes immediately after the log is saved
Root cause
In lib/widgets/routines/forms/log_form.dart, the async save closure calls setState() in try/catch/finally after await addLog(...) without checking if (mounted) first. If the widget unmounts while the async operation is in flight, Flutter throws on setState of a disposed widget.
Additionally, setState(() { _isSaving = false; }) is called redundantly in both the try block and the finally block, so it always runs twice on success.
Current code (v1.10.2, log_form.dart)
try {
await provider.Provider.of<RoutinesProvider>(context, listen: false).addLog(logToSave!);
// ...
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(...); // ✅ mounted check here
}
widget.controller.nextPage(...);
setState(() { _isSaving = false; }); // ❌ no mounted check
} on WgerHttpException {
setState(() { _isSaving = false; }); // ❌ no mounted check, redundant with finally
rethrow;
} finally {
setState(() { _isSaving = false; }); // ❌ no mounted check
}
Proposed fix
Remove the redundant setState calls in try and catch, keep only the finally block wrapped with if (mounted):
try {
await provider.Provider.of<RoutinesProvider>(context, listen: false).addLog(logToSave!);
// ...
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(...);
}
widget.controller.nextPage(...);
// setState removed here — finally handles it
} on WgerHttpException {
rethrow; // setState removed — finally handles it
} finally {
if (mounted) { // ✅ mounted check added
setState(() { _isSaving = false; });
}
}
Environment
- App version: 1.10.1 (build 180) and 1.10.2 (bug present in both)
- Platform: Android
- Server: self-hosted wger instance
Bug description
When saving a workout log in gym mode, the app crashes with:
The log is saved correctly on the server (POST
/api/v2/workoutlog/returns 201), but the crash makes the user think it failed. On retry, duplicate log entries are created.Steps to reproduce
Root cause
In
lib/widgets/routines/forms/log_form.dart, the async save closure callssetState()intry/catch/finallyafterawait addLog(...)without checkingif (mounted)first. If the widget unmounts while the async operation is in flight, Flutter throws onsetStateof a disposed widget.Additionally,
setState(() { _isSaving = false; })is called redundantly in both thetryblock and thefinallyblock, so it always runs twice on success.Current code (v1.10.2, log_form.dart)
Proposed fix
Remove the redundant
setStatecalls intryandcatch, keep only thefinallyblock wrapped withif (mounted):Environment