immich-app/immich · error · Exception
User must be logged in to access trash
Error message
User must be logged in to access trash
What it means
Thrown by the timelineServiceProvider override in the Trash page when currentUserProvider is null. The Trash timeline requires a user id to call timelineFactoryProvider.trash(user.id); without an authenticated user the service cannot be built. It indicates the Trash screen was opened in an unauthenticated state.
Solutions
- Guard navigation so the Trash page is only reachable when a user is logged in.
- Wait for the auth state (AsyncValue) to resolve before building the provider override.
- Restore or refresh the session, then re-authenticate the user.
- Render a login/unauthenticated placeholder instead of throwing when user is null.
Example fix
// before
final user = ref.watch(currentUserProvider);
if (user == null) {
throw Exception('User must be logged in to access trash');
}
// after
final user = ref.watch(currentUserProvider);
if (user == null) {
return const SizedBox.shrink(); // or redirect to login
} Defensive patterns
Strategy: try-catch
Validate before calling
final user = ref.watch(currentUserProvider);
if (user == null) {
context.go('/login');
return;
} Type guard
bool isAuthenticated(User? u) => u != null && u.id.isNotEmpty;
Try / catch
try {
final timeline = ref.watch(timelineServiceProvider);
// render trash page
} catch (e) {
if (e.toString().contains('User must be logged in')) {
context.go('/login');
} else {
rethrow;
}
} Prevention
- Only navigate to Trash from authenticated UI
- Await auth state before watching user-scoped providers
- Handle token expiry with silent refresh
- Render an unauthenticated placeholder rather than throwing
When it happens
Trigger: Opening the Trash page before login, after session expiry/logout, or during app startup while auth state is still being restored and the provider reads null.
Common situations: Stale auth token expired server-side; a deep link to trash opened pre-login; navigating back to the tab after the user logged out on another device.
Related errors
- User must be logged in to access recently taken
- User must be logged in to video
- User must be logged in to access archive
- User must be logged in to access archive
- User must be logged in to access favorite
AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15).
Data as JSON: /api/errors/91ad817596d70d69.
Report an issue: GitHub.
Appendix: source
Thrown at mobile/lib/presentation/pages/trash.page.dart:27
import 'package:immich_mobile/providers/infrastructure/action.provider.dart';
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
import 'package:immich_mobile/providers/server_info.provider.dart';
import 'package:immich_mobile/providers/user.provider.dart';
import 'package:immich_mobile/widgets/common/confirm_dialog.dart';
import 'package:immich_mobile/widgets/common/immich_toast.dart';
@RoutePage()
class TrashPage extends StatelessWidget {
const TrashPage({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 trash');
}
final timelineService = ref.watch(timelineFactoryProvider).trash(user.id);
ref.onDispose(timelineService.dispose);
return timelineService;
}),
],
child: Timeline(
appBar: SliverAppBar(
title: Text(context.t.trash),
floating: true,
snap: true,
pinned: true,
centerTitle: true,
elevation: 0,
actions: const [_TrashKebabMenu()],
),
topSliverWidgetHeight: 24,View on GitHub (pinned to e55ac299a4)