libretro / libretro/RetroArch

(Android) External launch with an unresolvable `LIBRETRO` core path hangs on a black screen with no error at default log level

Open
#19,357 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C
Stars
14.1k
Forks
2.2k
Avg merge
7h 35m
Merged PRs (30d)
51

Description

Is there an existing issue for this?
  • This is a bug in RetroArch frontend
  • I have searched the existing issues
Description

When RetroArch is launched by an external frontend via RetroActivityFuture with a LIBRETRO extra pointing at a core that isn't installed, it neither reports an error nor exits. The activity displays, and the process then sits on a black window indefinitely at 0% CPU. I didn't get an ANR dialog.

At default log settings, logcat just stops after the environment banner:

I/RetroArch: [ENV] Default screenshot folder: "/sdcard/RetroArch/screenshots".

Nothing after that. Setting log_verbosity = "true" shows the cause:

W/RetroArch: --libretro argument "/data/data/com.retroarch.aarch64/cores/nestopia_libretro_android.so" is not a file, core name or directory. Ignoring.
E/RetroArch: [Core] Frontend is built for dynamic libretro cores, but path is not set. Cannot continue.
E/RetroArch: Fatal error received in: "init_libretro_symbols()"

There seem to be two problems here.

First, an explicit --libretro path that doesn't resolve is treated as non-fatal. It's logged at warning level and the argument is then dropped ("Ignoring."). Because it's dropped rather than kept, the fatal error a few lines later, "path is not set", can't say why it's unset or name the core that was requested. A path the caller passed explicitly seems different from an optional argument: if it can't be resolved, that looks like a hard failure. At minimum the warning should be an error, so it's visible at default verbosity.

Second, on Android the fatal path leaves a black window instead of terminating. After init_libretro_symbols() fails and core symbols unload, the activity stays alive and focused with nothing rendered, so from the user's side the launch has just frozen. Finishing the activity, ideally with a setResult so the calling frontend can react, or dropping to the RetroArch menu with a message, would both be an improvement.

Frontends can't work around this themselves. RetroArch's cores directory is private and 0700, so a calling app has no way to check whether a core is installed before launching. ES-DE's Android FAQ documents the same limitation and lists the resulting black screen as expected behaviour. That leaves RetroArch as the only place this can be diagnosed, and at the moment a missing core, a typo'd core name and a wrong cores directory all look identical to both the user and the frontend.

Possibly related: #17438 (open) hits the same "path is not set" / init_libretro_symbols() pair from a different trigger on desktop, which suggests this end state is unhandled generally rather than only on Android. #17433 is the same signature for Android external launch, fixed for the bare core name case.

Expected behavior

An unresolvable --libretro / LIBRETRO path should produce an error that names the path and is visible at default log level, and RetroArch should either exit or fall back to its own menu with a message on screen, rather than hanging on a black screen.

Steps to reproduce the bug
  1. Install RetroArch for Android and install at least one core (below uses fceumm), but not the core used in step 3 (below uses nestopia).

  2. Control, launch with a core that is installed. The game boots correctly:

am start -n com.retroarch.aarch64/com.retroarch.browser.retroactivity.RetroActivityFuture \
  -e ROM "/sdcard/roms/nes/somegame.zip" \
  -e LIBRETRO /data/data/com.retroarch.aarch64/cores/fceumm_libretro_android.so \
  -e CONFIGFILE /data/data/com.retroarch.aarch64/retroarch.cfg \
  -e DATADIR /data/data/com.retroarch.aarch64 \
  -e APK /data/app/com.retroarch.aarch64 \
  -e SDCARD /sdcard \
  -e EXTERNAL /sdcard/Android/data/com.retroarch.aarch64/files
  1. Now launch the identical Intent with a core that isn't installed:
am start -n com.retroarch.aarch64/com.retroarch.browser.retroactivity.RetroActivityFuture \
  -e ROM "/sdcard/roms/nes/somegame.zip" \
  -e LIBRETRO /data/data/com.retroarch.aarch64/cores/nestopia_libretro_android.so \
  -e CONFIGFILE /data/data/com.retroarch.aarch64/retroarch.cfg \
  -e DATADIR /data/data/com.retroarch.aarch64 \
  -e APK /data/app/com.retroarch.aarch64 \
  -e SDCARD /sdcard \
  -e EXTERNAL /sdcard/Android/data/com.retroarch.aarch64/files

Result: black screen. pidof com.retroarch.aarch64 shows the process alive, top shows 0.0% CPU, and it stays that way indefinitely. adb logcat contains no error.

  1. To see the cause, set log_verbosity = "true" in the config passed as CONFIGFILE and repeat step 3. The two errors quoted above then appear.
Version/Commit

1.22.2 (Git 69a4f0e), Android com.retroarch.aarch64, built Nov 20 2025, from retroarch.com

Bisect Results

No response

Present in the nightly version

Yes, this is reproduced in the nightly build

Platform & operating system

Android 13, aarch64 (AYN Thor).

Affected Cores

Not core specific. Reproduces with any core name that isn't present in the cores directory.

Environment information

Found while working on an Android frontend that launches RetroArch by Intent. Behaviour is the same whether the Intent comes from the frontend or from am start directly. 1.22.2 is the latest tagged release at the time of filing. I can attach a screenshot of the black screen if it's useful.

Disclaimer: Claude Code (Opus 5) helped me with this report.

Relevant log output
I/RetroActivity: isPlayStoreBuild: false
I/RetroActivity: isAndroidTV == false
I/RetroArch: [ENV] Android version (major : 13, minor : 0, rel : 0)
I/RetroArch: [ENV] Checking arguments passed from intent ...
I/RetroArch: [ENV] Config file: "/data/data/com.retroarch.aarch64/retroarch.cfg".
I/RetroArch: [ENV] Libretro path: "/data/data/com.retroarch.aarch64/cores/nestopia_libretro_android.so".
I/RetroArch: [ENV] Auto-start game "/sdcard/roms/nes/somegame.zip".
I/RetroArch: [ENV] Android internal storage location: "/sdcard".
I/RetroArch: [ENV] APK location "/data/app/com.retroarch.aarch64".
I/RetroArch: [ENV] Android external files location "/sdcard/Android/data/com.retroarch.aarch64/files".
I/RetroArch: [ENV] App dir: "/data/data/com.retroarch.aarch64".
I/RetroArch: Testing permissions for /sdcard
I/RetroArch: Create /sdcard/.retroarch in /sdcard true
I/RetroArch: [ENV] Application location: "/data/data/com.retroarch.aarch64".
I/RetroArch: [ENV] Default savefile folder: "/sdcard/RetroArch/saves".
I/RetroArch: [ENV] Default savestate folder: "/sdcard/RetroArch/states".
I/RetroArch: [ENV] Default system folder: "/sdcard/RetroArch/system".
I/RetroArch: [ENV] Default screenshot folder: "/sdcard/RetroArch/screenshots".
E/ActivityTaskManager: Displayed com.retroarch.aarch64/...RetroActivityFuture: +118ms
I/RetroActivity: isSustainedPerformanceModeSupported? false
[ nothing further, process remains alive at 0% CPU on a black screen ]


With log_verbosity = "true", same launch:


W/RetroArch: --libretro argument "/data/data/com.retroarch.aarch64/cores/nestopia_libretro_android.so" is not a file, core name or directory. Ignoring.
I/RetroArch: RetroArch 1.22.2 (Git 69a4f0e)
I/RetroArch: === Build =======================================
I/RetroArch: Capabilities: ASIMD
I/RetroArch: [INFO] Version: 1.22.2
I/RetroArch: [INFO] Git: 69a4f0e
I/RetroArch: [INFO] Built: Nov 20 2025
I/RetroArch: [INFO] =================================================
I/RetroArch: [Input] Found input driver: "android".
E/RetroArch: [Core] Frontend is built for dynamic libretro cores, but path is not set. Cannot continue.
E/RetroArch: Fatal error received in: "init_libretro_symbols()"
I/RetroArch: [Core] Unloading core symbols...
[ process remains alive at 0% CPU on a black screen ]

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing the Android RetroActivityFuture launch path and the init_libretro_symbols() failure shown in the logs. Determine how an unresolved LIBRETRO path is discarded and how the fatal initialization result is handled after core symbols unload. Done means the requested path is reported at default log level and the Android launch exits or returns to a visible menu state instead of remaining on a black screen.

Written by the indexing model from the issue text.

Assessment

Tech stack
android, c
Domain
mobile-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.