{"record":{"id":"bb70f949483615bc","repo":"expo/expo","slug":"couldn-t-start-the-foreground-service-foreground","errorCode":null,"errorMessage":"Couldn't start the foreground service. Foreground service cannot be started when the application is in the background","messagePattern":"Couldn't start the foreground service\\. Foreground service cannot be started when the application is in the background","errorType":"exception","errorClass":"ForegroundServiceStartNotAllowedException","httpStatus":null,"severity":"error","filePath":"packages/expo-location/android/src/main/java/expo/modules/location/LocationModule.kt","lineNumber":331,"sourceCode":"\n    AsyncFunction<Boolean>(\"hasServicesEnabledAsync\") {\n      return@AsyncFunction LocationHelpers.isAnyProviderAvailable(mContext)\n    }\n\n    AsyncFunction(\"startLocationUpdatesAsync\") { taskName: String, options: LocationTaskOptions ->\n      val shouldUseForegroundService = options.foregroundService != null\n\n      if (isMissingForegroundPermissions()) {\n        throw LocationBackgroundUnauthorizedException()\n      }\n      // There are two ways of starting this service.\n      // 1. As a background location service, this requires the background location permission.\n      // 2. As a user-initiated foreground service with notification, this does NOT require the background location permission.\n      if (!shouldUseForegroundService && isMissingBackgroundPermissions()) {\n        throw LocationBackgroundUnauthorizedException()\n      }\n      if (!AppForegroundedSingleton.isForegrounded && options.foregroundService != null) {\n        throw ForegroundServiceStartNotAllowedException()\n      }\n\n      if (shouldUseForegroundService && !hasForegroundServicePermissions()) {\n        throw ForegroundServicePermissionsException()\n      }\n\n      mTaskManager.registerTask(taskName, LocationTaskConsumer::class.java, options.toMutableMap())\n      return@AsyncFunction\n    }\n\n    AsyncFunction(\"stopLocationUpdatesAsync\") { taskName: String ->\n      mTaskManager.unregisterTask(taskName, LocationTaskConsumer::class.java)\n      return@AsyncFunction\n    }\n\n    AsyncFunction(\"hasStartedLocationUpdatesAsync\") { taskName: String ->\n      return@AsyncFunction mTaskManager.taskHasConsumerOfClass(taskName, LocationTaskConsumer::class.java)\n    }","sourceCodeStart":313,"sourceCodeEnd":349,"githubUrl":"https://github.com/expo/expo/blob/7da61120be99bcd9cc2e5dbdba6d803c21b5c68b/packages/expo-location/android/src/main/java/expo/modules/location/LocationModule.kt#L313-L349","documentation":"expo-location throws this when you ask it to start a location task configured with a `foregroundService` option while the Android app process is not in the foreground. Android 12+ (API 31) forbids apps from starting foreground services from the background, so the module checks AppForegroundedSingleton before registering the task and fails fast with ForegroundServiceStartNotAllowedException instead of letting the OS kill the start attempt.","triggerScenarios":"Calling Location.startLocationUpdatesAsync / startLocationTaskAsync with `foregroundService: {...}` set while ActivityManager.getRunningAppProcesses reports the app is not foregrounded — e.g. invoked from a headless task manager callback, background fetch, or a notification tap handler that runs before the activity resumes.","commonSituations":"Restarting continuous location tracking from a background task after the OS killed the app; scheduling location updates from a push handler; a JS timer or task-manager callback firing after the user backgrounds the app; testing on Android 12+ emulators where the activity is not focused.","solutions":["Ensure the call runs only while the app is foregrounded: check AppState/AppLifecycle state before calling and defer the start until the activity resumes.","Remove the `foregroundService` option (use plain background location with BACKGROUND_LOCATION permission) if updates must start from the background.","Start the service from a user-visible interaction (notification button, activity) rather than a background callback.","On Android 12+, if a legitimate background start is needed, have the user grant exact-alarm/exemption paths or use a foregroundServiceType-compatible restart via the system (e.g. from an existing foreground service context)."],"exampleFix":"// before\nawait Location.startLocationUpdatesAsync(TASK, {\n  foregroundService: { notificationTitle: 'Tracking' },\n});\n\n// after\nif (AppState.currentState !== 'active') {\n  // defer until foregrounded, or drop foregroundService\n  return;\n}\nawait Location.startLocationUpdatesAsync(TASK, {\n  foregroundService: { notificationTitle: 'Tracking' },\n});","handlingStrategy":"try-catch","validationCode":"import { AppState } from 'react-native';\nfunction canStartForegroundLocation() {\n  return AppState.currentState === 'active';\n}","typeGuard":null,"tryCatchPattern":"try {\n  await Location.startLocationUpdatesAsync(TASK, { foregroundService: opts });\n} catch (e) {\n  if (String(e.message).includes('Foreground service cannot be started when the application is in the background')) {\n    // defer until app returns to foreground\n    AppState.addEventListener('change', (s) => { if (s === 'active') restart(); });\n  } else throw e;\n}","preventionTips":["Only call startLocationUpdatesAsync with foregroundService from user-visible, foregrounded code paths.","Guard background-triggered starts with an AppState/lifecycle check.","Prefer BACKGROUND_LOCATION permission for background-only tracking instead of foregroundService."],"tags":["android","foreground-service","background-execution","expo-location"],"backgroundTag":"foreground-service-start-not-allowed","analyzedSha":"7da61120be99bcd9cc2e5dbdba6d803c21b5c68b","analyzedAt":"2026-09-09T16:01:44.845Z","contentChangedAt":"2026-09-09T16:01:44.845Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}