Use ChatGPT for Kotlin without turning cancellation into an empty result

Give ChatGPT the coroutine boundary, its caller and the actual catch clauses when a cancelled load appears to succeed with no records. Ask it to trace cancellation separately from a recoverable load failure. A broad catch can turn a lifecycle signal into an ordinary return value, even though the coroutine's job remains cancelled.

For this task, the important question is what the caller observes. An empty list, a failed request and a cancelled request represent different outcomes. Decide which ordinary failures may become an empty list before asking for a patch.

Find the catch that changes the outcome

This original teaching fragment assumes fetchLabels() is a suspending function returning List<String> and that cancellation occurs at its cancellable suspension point:

suspend fun labelsOrEmpty(): List<String> {
    return try {
        fetchLabels()
    } catch (failure: Exception) {
        emptyList()
    }
}

CancellationException is an exception too. Under the stated trigger, this catch returns an empty list from the function instead of propagating cancellation. It does not reactivate the job. A later cancellable suspension can still throw because the job is already cancelled; therefore “the function returned” does not establish that the surrounding operation recovered.

Android's coroutine best practices, checked October 24, 2026, says to preserve CancellationException when catching exceptions. Its recommendation also helps separate errors you intend to handle from unrelated programming failures.

Preserve cancellation before handling an ordinary failure

If the existing contract deliberately converts ordinary Exception failures to an empty list, the smallest cancellation-specific repair is:

import kotlinx.coroutines.CancellationException

suspend fun labelsOrEmpty(): List<String> {
    return try {
        fetchLabels()
    } catch (cancelled: CancellationException) {
        throw cancelled
    } catch (failure: Exception) {
        emptyList()
    }
}

The first catch rethrows the original signal. The second preserves the example's existing fallback policy. In a real repository, consider catching only the documented recoverable failure type; narrowing that policy is a separate decision from repairing cancellation propagation.

These are source-level examples, not recorded Kotlin executions. Keep the project's installed Kotlin and kotlinx.coroutines versions with any reproduction. A fragment without the actual fetch implementation and caller cannot establish the application's complete cancellation behavior.

Ask for two separate traces

Review this Kotlin suspend function for cancellation handling.
Kotlin and kotlinx.coroutines versions: [ENTER]
Function, fetch implementation and complete relevant caller: [PASTE]
Coroutine scope/job owner and cancellation trigger: [ENTER]
Ordinary failure types allowed to produce an empty list: [ENTER]
Actual result or trace: [PASTE OR NOT YET RUN]

Trace cancellation and a permitted ordinary failure separately.
Identify any catch that consumes CancellationException. Preserve its
propagation and the existing approved fallback policy. Do not imply
that returning a value reactivates a cancelled job. Explain how the
caller distinguishes a valid empty result, failure and cancellation.
Return a small patch and concrete test expectations. Separate source
reasoning from tests actually executed in the stated environment.

OpenAI's prompting guidance supports supplying context and boundaries. Here, the scope owner and permitted fallback types carry the requirements that a general “fix coroutine errors” request leaves out.

Check the cancellation path directly

Use the existing coroutine test tools to arrange a fetch that suspends, signal that it reached that point, cancel its owning job and inspect completion. Confirm that cancellation is propagated rather than recorded as an ordinary empty success. Then run a separate permitted-failure case and a genuinely empty-success case. Avoid relying on a sleep to prove where cancellation happened.

The Go pipeline guide handles a different shutdown problem: a producer blocked after its consumer exits. Here, retain the cancellation-specific test beside the catch clauses so a later fallback edit cannot silently change the caller's outcome again.

Keep reading