When a phase cannot produce real data, the pipeline emits BLOCKED with an explicit blocked_reason rather than fabricating output. This guide walks through the most common cases and the order to check them.
| Symptom | Most likely cause | Detailed guide |
|---|---|---|
Detect version change says no Gradle catalog change found |
The PR doesn’t touch gradle/libs.versions.toml. |
L1 |
Report shows 0 impacted files for an AGP / KSP / wrapper bump |
Build plugin — no Kotlin imports to walk. | L2 |
source_set = "unknown" in the report |
Non-convention source layout. | L3 |
Dynamic analysis: BLOCKED — DroidBot produced no UTG artifact |
No APK or DroidBot failure. | L4 |
Deploy report to GitHub Pages ends cancelled |
Concurrent Pages deploys. | L6 |
| Static F1 unexpectedly low for Compose Multiplatform | Mapping gap. | L7 |
| Files that use DI bindings are not flagged | DI not in the import graph. | L8 |
BLOCKED — triage orderThis is the most common case. Check in order:
Detect Android app module — must resolve a real module. The workflow probes shared, composeApp, androidApp, app, common, kmm-shared, kmpShared in that order, then falls back to :app. If none of these match your real module name, expose it under one of those aliases.Ensure Gradle wrapper is recent enough for AGP — must show ≥ 8.7 for AGP 8.x and ≥ 9.0 for AGP 9.x.Build BEFORE APK — must end with BEFORE APK: /tmp/before.apk.Build AFTER APK — same expectation.phase3/before-utg/ and phase3/after-utg/ must contain utg.js or utg.json. Empty directories are rejected on purpose.If the project uses Kotlin 2.x with Compose and the AFTER APK fails to build, the most common cause is a missing org.jetbrains.kotlin.plugin.compose plugin. Required additions:
```toml title=”gradle/libs.versions.toml” kotlin-compose = { id = “org.jetbrains.kotlin.plugin.compose”, version.ref = “kotlin” }
```kotlin title="<module>/build.gradle.kts"
plugins {
alias(libs.plugins.kotlin.compose)
}
Also place jvmToolchain(…) at the top of the kotlin { … } block, not inside a target.
actions/deploy-pages@v4 enforces concurrency at the repository level. When several Dependabot PRs finish at the same time, newer deploys cancel older ones.
Recovery:
gh run rerun <run-id> -R <owner>/<repo>
gh run watch <run-id> -R <owner>/<repo>
For multi-PR bursts, re-run cancelled deploys serially — wait for each gh run watch to return before launching the next one.
UIRegressions — the blocked status enum.