immich-app/immich · error · Exception
User must be logged in to view person timeline
Error message
User must be logged in to view person timeline
What it means
This exception is thrown by the person page's timelineServiceProvider override when currentUserProvider is null. The person timeline requires both the logged-in user id and the person id (timelineFactoryProvider.person(user.id, _person.id)), so a null user makes the service unconstructible and the provider throws. It means the person timeline page was built without an authenticated session.
Solutions
- Gate person routes on a non-null currentUser via a router redirect to the login page.
- Complete auth restoration before restoring the navigation stack that contains the person page.
- Ensure currentUserProvider is backed by the live auth stream and updated on login/logout.
- Handle auth errors in the stream so a transient failure does not leave currentUser null while the app is signed in.
Example fix
// before
Navigator.of(context).push(PersonPage.route(person));
// after
final user = ref.read(currentUserProvider);
if (user == null) {
context.go('/login');
} else {
Navigator.of(context).push(PersonPage.route(person));
} Defensive patterns
Strategy: validation
Validate before calling
final user = ref.read(currentUserProvider);
if (user == null) {
context.go('/login');
return;
} Type guard
bool isSignedIn(User? user) => user != null && user.id.isNotEmpty;
Try / catch
try {
final service = ref.read(timelineServiceProvider);
} catch (e) {
if (e.toString().contains('User must be logged in')) {
context.go('/login');
} else {
rethrow;
}
} Prevention
- Route person links/notifications through an auth guard before pushing the page.
- Complete sign-in before restoring a saved navigation stack containing person pages.
- Keep currentUserProvider driven by the live auth state stream.
- Navigate away on logout so person pages never rebuild with a null user.
- Cover person deep links with a signed-out integration test.
When it happens
Trigger: Reading timelineServiceProvider on the person page while currentUserProvider is null — auth stream not yet emitted, session cleared by logout/expiry, or navigation to a person before login finishes.
Common situations: Tapping a person notification/deep link before the app finishes sign-in; session expiry while browsing a person timeline; app state restoration pushing this page ahead of the login gate.
Related errors
- User must be logged in to access archive
- User must be logged in to access favorite
- User must be logged in to access locked folder
- User must be logged in to access recently taken
- User must be logged in to access archive
AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15).
Data as JSON: /api/errors/38ee698fa0033def.
Report an issue: GitHub.
Appendix: source
Thrown at mobile/lib/presentation/pages/person.page.dart:82
},
onEditBirthday: () async {
await handleEditBirthday(context);
ContextHelper(context).pop();
},
birthdayExists: _person.birthDate != null,
);
},
);
}
@override
Widget build(BuildContext context) {
return ProviderScope(
overrides: [
timelineServiceProvider.overrideWith((ref) {
final user = ref.watch(currentUserProvider);
if (user == null) {
throw Exception('User must be logged in to view person timeline');
}
final timelineService = ref.watch(timelineFactoryProvider).person(user.id, _person.id);
ref.onDispose(timelineService.dispose);
return timelineService;
}),
],
child: Timeline(
appBar: PersonSliverAppBar(
person: _person,
onNameTap: () => handleEditName(context),
onBirthdayTap: () => handleEditBirthday(context),
onShowOptions: () => showOptionSheet(context),
),
),
);
}
}View on GitHub (pinned to e55ac299a4)