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

No one assigned

    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