immich-app/immich · error · Exception

User must be logged in to access favorite

Error message

User must be logged in to access favorite

What it means

This exception is thrown by the favorite page's timelineServiceProvider override when currentUserProvider evaluates to null. The favorite timeline service is constructed via timelineFactoryProvider.favorite(user.id), which is impossible without a logged-in user, so the provider throws deliberately instead of building a broken service. It signals that the page was reached without an authenticated session.

Solutions

  1. Gate navigation to the favorite page behind a non-null currentUser (auth redirect/guard).
  2. Ensure session restoration runs on app start before any tab/route can be built.
  3. Check that currentUserProvider is properly overridden/initialized in the root ProviderScope for this route.
  4. On logout, navigate away from auth-required pages instead of leaving them in the tree.

Example fix

// before
timelineServiceProvider.overrideWith((ref) {
  final user = ref.watch(currentUserProvider);
  if (user == null) {
    throw Exception('User must be logged in to access favorite');
  }
  ...
// after
timelineServiceProvider.overrideWith((ref) {
  final user = ref.watch(currentUserProvider);
  if (user == null) {
    return Future.value(null); // let the page render a login prompt instead of throwing
  }
  ...
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

When it happens

Trigger: Reading timelineServiceProvider on the favorite page while currentUserProvider is null — e.g. the auth stream has not emitted yet, the user logged out, or the page is opened before login completes.

Common situations: Deep link or push notification opening the favorites tab before auth bootstrap finishes; session expiry clearing the user while the favorites page stays mounted; auth provider misconfiguration so currentUser never becomes non-null.

Related errors


AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15). Data as JSON: /api/errors/5b630a53cab96d94. Report an issue: GitHub.

Appendix: source

Thrown at mobile/lib/presentation/pages/favorite.page.dart:22

import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/presentation/widgets/bottom_sheet/favorite_bottom_sheet.widget.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 FavoritePage extends StatelessWidget {
  const FavoritePage({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 favorite');
          }

          final timelineService = ref.watch(timelineFactoryProvider).favorite(user.id);
          ref.onDispose(timelineService.dispose);
          return timelineService;
        }),
      ],
      child: Timeline(
        appBar: MesmerizingSliverAppBar(title: context.t.favorites, icon: Icons.favorite_outline),
        bottomSheet: const FavoriteBottomSheet(),
      ),
    );
  }
}

View on GitHub (pinned to e55ac299a4)