Skip to content

Troubleshooting

aaalllexxx edited this page Jun 29, 2026 · 2 revisions

Troubleshooting

Run paf doctor first — it diagnoses the most common build-environment problems.

Build environment

"No compatible Java found" / Gradle fails to start

Gradle 8.4 + AGP 8.2 need JDK 17–21. JDK 22+ can't even run Gradle 8.4. If your default java is newer (e.g. JDK 25), ENPAF tries to auto-detect a usable JDK 17 and pin JAVA_HOME for the build — but the reliable fix is to install JDK 17 and point JAVA_HOME at it:

setx JAVA_HOME "C:\Program Files\Eclipse Adoptium\jdk-17.0.x-hotspot"

Open a new terminal and re-run the build.

"Android SDK not found"

Install Android Studio (bundles the SDK) or set ANDROID_HOME:

setx ANDROID_HOME "%LOCALAPPDATA%\Android\Sdk"

"Unable to delete directory … a process has files open" (Windows/OneDrive)

OneDrive's "Files On-Demand" keeps file handles / read-only placeholders, which breaks Gradle's own delete steps. ENPAF works around this by relocating the build outside OneDrive to %LOCALAPPDATA%\enpaf\builds\<name>-<hash>. If you still hit locks:

  • Pause OneDrive sync during builds, or

  • Set ENPAF_BUILD_DIR to a path outside any synced folder:

    $env:ENPAF_BUILD_DIR = "D:\enpaf-builds"

WinError 5 (Access Denied) during project generation

Same root cause (OneDrive read-only placeholders). ENPAF clears read-only bits before overwriting; if it persists, pause OneDrive or build from a non-synced folder.

The first build hangs / takes forever

The first build downloads the Gradle distribution and Android dependencies and Chaquopy assembles the Python runtime. Let it finish once; later builds reuse the cache.

App crashes on launch (on-device)

ModuleNotFoundError immediately on launch

A bundled Python module imported a third-party library at module top level. Chaquopy only ships the stdlib + your python_requirements. Fixes:

  • Move the import inside the function that uses it (lazy import).
  • Or add the package to enpaf.json python_requirements so Chaquopy bundles it.

(That's exactly why the framework imports Jinja2 lazily — see Architecture → Runtime constraints.)

Crash when writing data / SQLite errors

The app's source files are packaged read-only. Don't write next to them — use Storage (which writes to ENPAF_DATA_DIR) or read ENPAF_DATA_DIR yourself. See Storage.

Changes don't show up after rebuilding

An already-installed APK keeps the old code. Rebuild and reinstall:

paf build apk && adb install -r dist/<name>-<version>.apk

A rebuilt APK won't install over the old one

If installing a new build silently fails (or the device clearly keeps the old one), check the version. The builder derives versionCode from enpaf.json version:

versionCode = major*10000 + minor*100 + patch

Rebuilding the same version (e.g. 1.0.3 twice) produces the same versionCode, and Android refuses to install an update with an equal (or lower) versionCode over an existing app. Fix: bump version in enpaf.json before rebuilding an update — e.g. 1.0.31.0.4. If you must keep the version, fully uninstall the old app first (adb uninstall <package>).

Diagnosing a fresh crash

If a freshly built APK still crashes, capture logs instead of guessing:

adb logcat | findstr /R "AndroidRuntime python.stderr chaquopy"

(grep -E on macOS/Linux.) The Python traceback usually appears under python.stderr.

Runtime / bridge

No module named 'android' when reaching Android APIs

Use from android.provider import Settings, not import android.provider.Settings as Settings. The aliased form runs a bare import android first, which Chaquopy can't resolve.

A JS enpaf.on(...) event never fires

You probably emitted with app.events.emit(...) (Python-only) instead of app.emit(...) (Python and JS). Use app.emit for anything the UI must receive. See Events.

A permission prompt never appears / feature silently fails

Dangerous permissions need a runtime request, not just an enpaf.json entry:

await enpaf.permissions.request(["CAMERA"]);

Confirm the permission is also declared in enpaf.json permissions.

Camera preview is black / getUserMedia does nothing

For a WebView camera (e.g. a QR scanner) you need all of:

  1. The runtime CAMERA permission (await enpaf.permissions.request(["CAMERA"])).
  2. The WebView to grant onPermissionRequest and set setMediaPlaybackRequiresUserGesture(false) so the preview <video> autoplays — the framework's generated MainActivity does both (rebuild with a current framework).
  3. The camera JS library bundled locally, not loaded from a CDN — the dev LAN often has no internet, so a CDN <script> never loads and the scanner can't start.

Release APK won't install

An unsigned release APK can't be installed. ENPAF signs release builds automatically; if you supplied a custom signing block or --keystore, verify the keystore path and passwords. See Release & Signing.

Dev server

Bridge calls fall back to HTTP / WebSocket won't connect

The JS bridge uses Socket.IO with an HTTP fallback (/enpaf-api/bridge-call), so calls still work. If you need WebSocket specifically, ensure flask-socketio and simple-websocket are installed and no proxy is stripping the upgrade.

Port already in use

paf run --port 3000

Still stuck?

Open an issue at https://github.com/aaalllexxx/enpaf/issues with paf doctor output and (for on-device crashes) the relevant adb logcat lines.

Clone this wiki locally