kotlin-coroutines-structured-concurrency

Detects and fixes Kotlin coroutine anti-patterns like stored scopes, swallowed cancellation, and runBlocking misuse.

Updated Jul 1, 2026
One-click install
npx skills add https://github.com/w0lzard/Wolzard-s-Marketplace --skill kotlin-coroutines-structured-concurrency-w0lzard
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: kotlin-coroutines-structured-concurrency
Source: https://github.com/w0lzard/Wolzard-s-Marketplace/tree/main/plugins/personal-skills/skills/kotlin-coroutines-structured-concurrency
Command: npx skills add https://github.com/w0lzard/Wolzard-s-Marketplace --skill kotlin-coroutines-structured-concurrency-w0lzard

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve? Kotlin codebases often hide dangerous coroutine bugs: classes that store a CoroutineScope silently stop doing work after cancellation, init-block launches make startup behavior invisible, and broad catch blocks swallow CancellationException so cancelled work keeps running. This Skill gives you a systematic checklist to find these anti-patterns during code review and the exact refactoring to fix each one. ## Core Features & Use Cases - Anti-pattern detection: Identifies stored CoroutineScope properties, init-block launches, fire-and-forget APIs on non-UI classes, DI-bound singletons that launch from constructors, swallowed CancellationException, and runBlocking misuse. - Concrete fixes with code examples: Each anti-pattern pairs a bad snippet with a corrected version, usually converting the API to suspend and letting the caller own the scope. - Carve-outs and boundaries: Documents legitimate exceptions such as the UI state-holder boundary (viewModelScope in ViewModels), ContentProvider's synchronous surface, and Initializer classes that only register listeners. - Use Case: While reviewing a pull request, you spot a repository with private val scope: CoroutineScope and a fun refresh() { scope.launch { ... } }. Use this Skill to confirm the anti-pattern, explain the silent-cancellation risk, and refactor it to suspend fun refresh() with the ViewModel owning the scope. ## Quick Start Review this Kotlin file for coroutine structured-concurrency anti-patterns and suggest fixes for any stored scopes, init launches, swallowed cancellation, or runBlocking usage.

Frequently Asked Questions about kotlin-coroutines-structured-concurrency

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I fix a class that stores a CoroutineScope as a property?

Remove the stored CoroutineScope and convert the public functions that launched on it into suspend functions. The caller, typically a ViewModel or use case, then chooses the scope, error handling, and cancellation semantics explicitly.

Why is launching a coroutine from an init block dangerous?

An init-block launch is a construction-time side effect the caller cannot await, cancel, or observe for errors. If the scope is later cancelled, subsequent launches silently do nothing. Move the work into an explicit suspend fun init() the caller invokes.

When is it acceptable for a ViewModel to call viewModelScope.launch?

It is correct when three conditions hold: the class is a UI state holder, the scope is lifecycle-bound like viewModelScope, and the caller is a genuine UI event such as a Composable onClick. Repositories and use cases underneath should still expose suspend APIs.

How do I catch exceptions around a suspend call without breaking cancellation?

Add a catch (e: CancellationException) { throw e } clause before any broad catch, or check if (e is CancellationException) throw e inside it. With runCatching, rethrow CancellationException in onFailure or terminate with getOrThrow().

Should I use runBlocking or runTest in Kotlin unit tests?

Use runTest in unit tests. It provides virtual time so delay() returns immediately, integrates with TestDispatcher, and cleans up coroutines properly, while runBlocking runs in real time and makes tests slow and flaky.

When is runBlocking acceptable in Android application code?

runBlocking is acceptable only at genuine synchronous boundaries such as ContentProvider member functions, CLI main functions, or Java interop APIs with no suspending alternative. Keep the blocking body minimal and call into suspending code immediately.