BGProcessingTask expirationHandler — No way to distinguish expiration reason

The expirationHandler on BGProcessingTask is a () -> Void closure. It provides no information about why it was called.

In my testing, all of the following trigger the same handler:

  1. Time expiration
  2. Resource pressure (CPU, memory, battery)
  3. Not reporting progress
  4. User tapping "Stop" on the Live Activity

There is no way for the app to tell these apart.

Questions:

Q1. Is there an official, complete list of all conditions that trigger expirationHandler? The documentation only mentions "time expires."

Q2. What is the specific time limit before timeout? If it varies by device state, what are the conditions?

Q3. A way to distinguish the reason is needed. "User stop" and "system expiration" require completely different handling. Currently this is impossible.

Environment: iOS 26, physical device

Answered by DTS Engineer in 880135022

Q1. Is there an official, complete list of all conditions that trigger expirationHandler? The documentation only mentions "time expires."

No, but the primary causes are user cancellation and failure to report progress. Theoretically, resource pressure could cause it; however, in practice, I think the system typically ends up killing your app instead[1].

Q2. What is the specific time limit before timeout? If it varies by device state, what are the conditions?

There isn't any specific time limit. I've never worked out what the "absolute" maximum (defined by the progress reporting requirement) is, but that limit would be high enough that it's not really a constraint.

Q3. A way to distinguish the reason is needed. "User stop" and "system expiration" require completely different handling. Currently, this is impossible.

Yes, this is definitely an issue with the API. Please file an enhancement request asking for this, then post the bug number back here.

[1] The issue here is similar to (one of…) the reason why memory pressure warnings are relatively rare. In practice, sudden memory resource “spikes” are what typically lead to these issues and those happen faster than the system could notify you.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Is there an official, complete list of all conditions that trigger expirationHandler?

No. It’s unlikely that we would ever publish such a list because it’s an implementation detail, one that we want to be able to change as the system evolves.

What is the specific time limit before timeout?

Again, this is something we specifically don’t document.

A way to distinguish the reason is needed. "User stop" and "system expiration" require completely different handling.

I was investigating this when I realised that I’m confused about the context here. You mention BGProcessingTask but those tasks don’t have a UI presence. Are you actually using BGContinuedProcessingTask?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thank you. please understand that I am using BGContinuedProcessingTask. I misspoke earlier when I referred to BGProcessingTask.

Could you please answer my previous question again in the context of BGContinuedProcessingTask?

I don’t think so, but lemme double check and get back to you.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Q1. Is there an official, complete list of all conditions that trigger expirationHandler? The documentation only mentions "time expires."

No, but the primary causes are user cancellation and failure to report progress. Theoretically, resource pressure could cause it; however, in practice, I think the system typically ends up killing your app instead[1].

Q2. What is the specific time limit before timeout? If it varies by device state, what are the conditions?

There isn't any specific time limit. I've never worked out what the "absolute" maximum (defined by the progress reporting requirement) is, but that limit would be high enough that it's not really a constraint.

Q3. A way to distinguish the reason is needed. "User stop" and "system expiration" require completely different handling. Currently, this is impossible.

Yes, this is definitely an issue with the API. Please file an enhancement request asking for this, then post the bug number back here.

[1] The issue here is similar to (one of…) the reason why memory pressure warnings are relatively rare. In practice, sudden memory resource “spikes” are what typically lead to these issues and those happen faster than the system could notify you.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

BGProcessingTask expirationHandler — No way to distinguish expiration reason
 
 
Q