immich-app/immich · error · Exception
User must be logged in to access recently taken
Error message
User must be logged in to access recently taken
What it means
This exception is thrown by the recently-added page's timelineServiceProvider override when currentUserProvider yields null. The recently-taken timeline is user-scoped (timelineFactoryProvider.recentlyAdded(user.id)), so it cannot be built without a logged-in user; the provider throws this exception instead. It indicates the page was reached before authentication resolved.
Solutions
- Show a loading/login screen until currentUserProvider emits a user before rendering any timeline tab.
- Persist and restore the session on startup so currentUser is available at first build.
- Add a router redirect guarding all timeline pages behind authentication.
- Confirm the auth provider is correctly initialized/overridden in the root ProviderScope.
Example fix
// before final timelineService = ref.watch(timelineServiceProvider); // after final user = ref.watch(currentUserProvider); if (user == null) return const LoginPage(); final timelineService = ref.watch(timelineServiceProvider);
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
- Render a login/loading screen until currentUser resolves before showing timeline tabs.
- Restore the persisted session during app startup before first frame navigation.
- Guard all timeline routes with a single shared auth redirect.
- Ensure auth provider initialization is not skipped in any build flavor.
- Write a cold-start signed-out test that opens the recently-added tab.
When it happens
Trigger: Opening the recently added page while currentUserProvider is null — first frame before auth initialization, logout clearing the user, or a route pushed without the login gate.
Common situations: App cold start landing on the recently-taken tab before session restore completes; auth token expiring silently so the user becomes null while the tab stays mounted; forgetting to initialize the auth provider in a test/dev build.
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 view person timeline
- User must be logged in to access archive
AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15).
Data as JSON: /api/errors/2b57be65e5dfa026.
Report an issue: GitHub.
Appendix: source
Thrown at mobile/lib/presentation/pages/recently_added.page.dart:21
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/presentation/widgets/timeline/timeline.widget.dart';
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
import 'package:immich_mobile/providers/user.provider.dart';
import 'package:immich_mobile/widgets/common/mesmerizing_sliver_app_bar.dart';
@RoutePage()
class RecentlyAddedPage extends StatelessWidget {
const RecentlyAddedPage({super.key});
@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 access recently taken');
}
final timelineService = ref.watch(timelineFactoryProvider).recentlyAdded(user.id);
ref.onDispose(timelineService.dispose);
return timelineService;
}),
],
child: Timeline(appBar: MesmerizingSliverAppBar(title: context.t.recently_added)),
);
}
}
View on GitHub (pinned to e55ac299a4)