Linux AppImage: WebKitWebProcess SIGABRT in createAudioSink — GST_PLUGIN_SYSTEM_PATH points at missing plugin dirs
- Dominant language
- TypeScript
- Stars
- 909
- Forks
- 116
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 156
Description
## Summary
Berd 0.6.2's Linux AppImage aborts `WebKitWebProcess` (`SIGABRT` / `SI_TKILL`) a few seconds after first launch. The UI process stays up, so the window goes blank rather than the whole app disappearing.
This is the same packaging hole Buzz already diagnosed and fixed in [block/buzz#2176](https://github.com/block/buzz/pull/2176). Berd did not get that shim.
## Environment
- Berd 0.6.2 extracted AppImage (`~/.local/opt/berd/squashfs-root`)
- OS: Omarchy 4.0.0 (Arch Linux)
- Session: Hyprland / Wayland; `GDK_BACKEND=x11` (linuxdeploy GTK hook)
- GPU: NVIDIA GeForce RTX 3060 Ti, driver 610.57.04
- Host GStreamer: 1.28.6 (`gst-plugins-base` installed)
- Bundled WebKitGTK 4.1 GNU build-id `2594e661ffa45aa2a47f83c2f2f10caaec9e273f`
Not an OOM: ~9 GiB free, no oom-kill in the journal.
## What happens
1. Launch Berd (`gtk-launch Berd.desktop`).
2. First-load renderer boots (`[renderer] renderer booted (first load this install)`).
3. ~8s later `WebKitWebProcess` calls `abort()`. systemd-coredump records it.
4. Main `Berd` process keeps running (ACP/npm install, goose serve). No replacement web process is spawned.
Reproduced twice on this machine (PIDs 116183 at 12:02 and 119514 at 12:11 NZST, 2026-08-25). Same abort offsets both times.
## Abort site (from the core)
`WTFCrashWithInfo` in:
- file: `Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp`
- function: `GstElement *WebCore::MediaPlayerPrivateGStreamer::createAudioSink()`
- line: 1585
That is `RELEASE_ASSERT(audioSink)` after `createPlatformAudioSink("video")` returned NULL. The crashing thread still held the role string `"video"`.
WebKit's binary also contains `GStreamer element %s not found. Please install it`.
## Root cause
linuxdeploy's `AppRun.wrapped` force-sets:
```
GST_PLUGIN_SYSTEM_PATH=$APPDIR/usr/lib/gstreamer:$GST_PLUGIN_SYSTEM_PATH
GST_PLUGIN_SYSTEM_PATH_1_0=$APPDIR/usr/lib/gstreamer-1.0:$GST_PLUGIN_SYSTEM_PATH_1_0
```
A **set** `GST_PLUGIN_SYSTEM_PATH_1_0` **replaces** GStreamer's compiled-in default search path. Those two directories do not exist in the Berd AppImage. Berd ships GStreamer *libraries* (`libgstreamer-1.0.so.0`, `libgstaudio-1.0.so.0`, …) but no plugin tree.
At the crash second, GStreamer wrote `~/.cache/gstreamer-1.0/registry.x86_64.bin` — 76 bytes, version `1.23.90`, **zero plugins**.
Berd's launcher (`~/.local/bin/Berd`) only sets `WEBKIT_DMABUF_RENDERER_FORCE_SHM=1` on NVIDIA. It does not undo the GST override. There is no equivalent of Buzz's `usr/bin/buzz-desktop` GST shim.
This is not the NVIDIA DMA-BUF protocol crash. `WEBKIT_DMABUF_RENDERER_FORCE_SHM=1` was already set.
## Expected
Missing audio sink should fail the media element, not `abort()` the renderer. The AppImage should either ship GStreamer plugins or not replace the host plugin path (Buzz #2176).
## Suggested fix
Port Buzz's `desktop/scripts/fix-appimage.sh` shim: after `AppRun.wrapped` rewrites `GST_PLUGIN_*`, drop values that point into `$APPDIR` so host GStreamer can resolve `autoaudiosink` / `appsink` / `appsrc`. Alternatively ship a real `usr/lib/gstreamer-1.0` plugin set built against the bundled GStreamer.
Also worth a private `GST_REGISTRY` under `~/.local/share/xyz.block.berd/` so the AppImage does not clobber the desktop-wide registry (see [block/buzz#2560](https://github.com/block/buzz/issues/2560)).
## Related
- Same abort, same WebKit build-id, on Buzz AppImage on this machine (filing separately).
- Not [block/buzz#2338](https://github.com/block/buzz/issues/2338) (DMA-BUF).
- Not [block/buzz#6339](https://github.com/block/buzz/issues/6339) (Ubuntu `.deb` + system webkit 2.52.3).
Contributor guide
Research direction
Start by locating how Berd generates AppRun.wrapped and its Linux launcher, then read Buzz's desktop/scripts/fix-appimage.sh referenced in the issue. Reproduce or inspect the GST_PLUGIN_SYSTEM_PATH values in an extracted AppImage. Done means the AppImage no longer replaces the host plugin path with missing $APPDIR directories, allowing the required GStreamer elements to resolve without the renderer aborting.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- linux, shell
- Domain
- build-system, desktop
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100