immich-app/immich · error · Exception

User must be logged in to access map

Error message

User must be logged in to access map

What it means

Thrown by the top-level mapServiceProvider Provider when currentUserProvider is null. MapService construction needs a user id (for user-scoped map queries), so reading it in an unauthenticated state throws at provider initialization. Any widget watching mapServiceProvider without a logged-in user hits this.

Solutions

  1. Gate map UI behind authenticated route guards so the provider is only read when a user exists.
  2. Make mapServiceProvider an AsyncProvider (or FutureProvider) that waits for auth state instead of throwing synchronously.
  3. Re-authenticate (token refresh/login) when this error is caught, then rebuild.
  4. Return null/safe fallback from dependent widgets when the user is absent.

Example fix

// before
final user = ref.watch(currentUserProvider);
if (user == null) {
  throw Exception('User must be logged in to access map');
}
// after
final user = ref.watch(currentUserProvider);
if (user == null) {
  return null; // in a Provider<Coordinates?> / async variant; callers handle null
}
Defensive patterns

Strategy: type-guard

Validate before calling

final user = ref.read(currentUserProvider);
if (user == null) {
  // do not watch mapServiceProvider; route to login
  return;
}
final mapService = ref.read(mapServiceProvider);

Type guard

bool canUseMapService(User? u) => u != null && u.id.isNotEmpty;

Try / catch

try {
  final mapService = ref.watch(mapServiceProvider);
  // use service
} on Exception catch (e) {
  if (e.toString().contains('User must be logged in')) {
    context.go('/login');
  } else {
    rethrow;
  }
}

Prevention

When it happens

Trigger: Watching mapServiceProvider while currentUserProvider is null — during app startup before auth resolves, after logout, or after token expiry cleared the user.

Common situations: Map tab rendered before login completes; session invalidated server-side while the map screen is open; auth restoration racing with the first frame that watches the provider.

Related errors


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

Appendix: source

Thrown at mobile/lib/providers/infrastructure/map.provider.dart:12

import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/services/map.service.dart';
import 'package:immich_mobile/presentation/widgets/map/map.state.dart';
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
import 'package:immich_mobile/providers/user.provider.dart';

final mapServiceProvider = Provider<MapService>(
  (ref) {
    final user = ref.watch(currentUserProvider);
    if (user == null) {
      throw Exception('User must be logged in to access map');
    }

    final users = ref.watch(mapStateProvider).withPartners
        ? ref.watch(timelineUsersProvider).valueOrNull ?? [user.id]
        : [user.id];

    final mapFactory = MapFactory(mapRepository: ref.watch(driftProvider).mapRepository);
    final mapService = mapFactory.remote(users, ref.watch(mapStateProvider).toOptions());
    return mapService;
  },
  // Empty dependencies to inform the framework that this provider
  // might be used in a ProviderScope
  dependencies: const [],
);

View on GitHub (pinned to e55ac299a4)