{"record":{"id":"2e203ef222ef52bd","repo":"immich-app/immich","slug":"user-must-be-logged-in-to-access-this-provider","errorCode":null,"errorMessage":"User must be logged in to access this provider","messagePattern":"User must be logged in to access this provider","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"mobile/lib/providers/user.provider.dart","lineNumber":37,"sourceCode":"      await _userService.refreshMyUser();\n    } catch (_) {}\n  }\n\n  @override\n  void dispose() {\n    unawaited(streamSub.cancel());\n    super.dispose();\n  }\n}\n\nfinal currentUserProvider = StateNotifierProvider<CurrentUserProvider, UserDto?>((ref) {\n  return CurrentUserProvider(ref.watch(userServiceProvider));\n});\n\nfinal authUserProvider = Provider<UserDto>((ref) {\n  final user = ref.watch(currentUserProvider);\n  if (user == null) {\n    throw Exception('User must be logged in to access this provider');\n  }\n  return user;\n});\n","sourceCodeStart":19,"sourceCodeEnd":41,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/mobile/lib/providers/user.provider.dart#L19-L41","documentation":"authUserProvider is a non-nullable Provider<UserDto> derived from currentUserProvider. Since currentUserProvider can legitimately be null (no signed-in user), the provider throws 'User must be logged in to access this provider' to convert the nullable state into an explicit error whenever something watches authUserProvider while logged out.","triggerScenarios":"Any widget or provider calls ref.watch(authUserProvider) / ref.read(authUserProvider) while currentUserProvider is null — typically before login completes, after logout, or when reading it in app-startup code that runs before auth restoration.","commonSituations":"A screen that assumes authentication is mounted at app start before the session is restored; logout triggers a rebuild of a still-active widget watching authUserProvider; tests forget to seed a user before watching the provider.","solutions":["Only watch/read authUserProvider from UI reachable exclusively after authentication (e.g. below a router guard that requires login).","Replace with ref.watch(currentUserProvider) and handle the null case in the consumer.","Make the provider nullable or return a UserDto? / AsyncValue to remove the throw.","Ensure auth state is restored before building screens that depend on authUserProvider."],"exampleFix":"// before\nfinal user = ref.watch(authUserProvider);\n// after\nfinal user = ref.watch(currentUserProvider);\nif (user == null) return const SignInPrompt();\n// use non-null user here","handlingStrategy":"type-guard","validationCode":"final maybeUser = ref.watch(currentUserProvider);\nif (maybeUser == null) return; // or show login UI\nfinal user = maybeUser;","typeGuard":"UserDto? userOrNull(Ref ref) => ref.watch(currentUserProvider);\nbool hasUser(Ref ref) => ref.watch(currentUserProvider) != null;","tryCatchPattern":"try {\n  final user = ref.read(authUserProvider);\n  useUser(user);\n} catch (e) {\n  if (e.toString().contains('User must be logged in')) {\n    navigateToLogin();\n  } else {\n    rethrow;\n  }\n}","preventionTips":["Prefer watching currentUserProvider (nullable) and handle null explicitly","Place authUserProvider consumers only inside authenticated route subtrees","Seed a user in tests before watching authUserProvider","Use router guards so logged-out states never build screens depending on it"],"tags":["auth","riverpod","mobile"],"backgroundTag":"authentication-required","analyzedSha":"e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c","analyzedAt":"2026-09-15T07:20:19.675Z","contentChangedAt":"2026-09-15T07:20:19.675Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}