Skip to content

Task cancellations surfaces as ApolloClient.Error.noResults instead of CancellationError when no results are emitted #3614

@3redrubies

Description

@3redrubies

Question

Summary

When a running query task is cancelled, Apollo currently throws ApolloClient.Error.noResults instead of propagating CancellationError. This happens when the query has not yet produced any results—for example when using .networkOnly or when the cache is empty.

The error description for ApolloClient.Error.noResults is:

The operation completed without returning any results. This can occur if the network returns a success response with no body content.
If using a `RequestChainNetworkTransport`, this can also occur if an interceptor fails to pass on the emitted results.

I’ve attached a simple project and a video that demonstrates the issue where cancellation consistently results in .noResults.

output.mp4

ApolloCancellationBug.zip

Environment

  • iOS version: 26.1
  • Xcode version: 26.1.1 (17B100)
  • macOS version: 26.1 (25B78)
  • Apollo iOS version: 2.0.3
  • Device / Simulator: 17 Pro

Where the behaviour occurs

In RequestChain, within:

private func kickoffRequestInterceptors(
  request initialRequest: Request,
  continuation: ResultStream.Continuation
) async throws

The relevant code path is:

var didEmitResult: Bool = false

for try await response in resultStream.getStream() {
  try Task.checkCancellation()

  try await writeToCacheIfNecessary(response: response, for: finalRequest)

  continuation.yield(response.result)
  didEmitResult = true
}

guard didEmitResult else {
  throw ApolloClient.Error.noResults
}

Observed behaviour

  • If at least one result is emitted before cancellation, Apollo would correctly propagate CancellationError.
  • If zero results are emitted before cancellation, the loop exits and falls through to the guard, which throws .noResults, effectively squashing the cancellation error.

Question

Is this behaviour intended? Would it make sense for Apollo to also check Task.isCancelled before throwing .noResults, so cancellations result in CancellationError?

This would allow us to reliably distinguish between (since the noResults error description doesn't match the behaviour):

  • “Cancelled before producing a result”
  • “Completed with no results”

Thanks!

Metadata

Metadata

Assignees

Labels

questionIssues that have a question which should be addressed

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions