Skip to content

App aborts on startup with SIGABRT: panic "should be initialized when used" (event/mod.rs:66) #7407

Open

Description

@inoX-Network

Reported to support first; they recommended opening an issue here.

Summary

On Linux, the Modrinth App 0.18.0 aborts about 1.5 s after launch with SIGABRT, showing no window and no error message. The frontend issues commands before initialize_state has finished, and the resulting panic is not survivable.

thread 'tokio-rt-worker' panicked at packages/app-lib/src/event/mod.rs:66:14:
should be initialized when used

Environment

Modrinth App 0.18.0 (Arch/AUR modrinth-app 0.18.0-1.1)
OS CachyOS (Arch-based), kernel 7.2.0
Session Wayland (KDE Plasma)
WebKitGTK 2.52.6-1
GPU AMD Radeon RX 9070 XT, Mesa 26.2.1

What happens

Clicking the application entry does nothing at all — no window, no error message. The process starts, aborts after roughly 1.5 seconds with exit code 134, and writes a core dump. Because nothing appears on screen, there is no indication of what went wrong.

It is a race, and both outcomes look identical at first

A failing start:

INFO  theseus_gui: Initializing app...
ERROR get_game_version_tags: theseus::state: Attempted to get state before
      it is initialized - this should never happen!
ERROR get_loader_tags: theseus::state: Attempted to get state before it is
      initialized - this should never happen!
<process aborts>

A successful start produces the exact same two errors, but survives because initialize_state completes moments later:

ERROR get_game_version_tags: ... Attempted to get state before it is initialized
ERROR get_loader_tags: ...      Attempted to get state before it is initialized
INFO  initialize_state: theseus_gui: Initializing app event state...
INFO  initialize_state: theseus::state: Connecting to app database

So those two error lines occur on every start. Whether the app survives them is a race between the WebView issuing its first commands and initialize_state finishing.

What appeared to decide the race: database open time

Measured from log timestamps between Connecting to app database and Fetching app settings:

Database open Situation Result
376 ms first ever launch, migrating settings version 1 → 3 crash
8 ms immediately afterwards, migration already done success

Later the same day the crash returned. By then app.db had grown from a few KB to 20.7 MB (5583 rows in the cache table). After running VACUUM on it (20.7 MB → 18.9 MB), the app started successfully 8 times in a row, from both the desktop entry and the command line.

To be precise: this is a correlation observed on a single machine, not proof. Since it is a race, individual runs can go either way. But the pattern was consistent — the slower the database opened, the more reliably it crashed.

Why this can lock a user out completely

On a fresh installation the failure is self-perpetuating:

  1. The settings migration (version 1 → 3) makes the first launch slow.
  2. The slow launch loses the race and aborts.
  3. The abort leaves the migration unfinished, so the next launch runs the same slow migration — and fails the same way.

I only escaped this loop by starting the app from a terminal and leaving it running long enough for the migration to complete. Clicking the icon would never have resolved it, and nothing on screen suggests otherwise.

Steps to reproduce

  1. Start with a fresh profile directory (no existing app.db)
  2. Launch the Modrinth App from the desktop entry
  3. It aborts within ~2 seconds, no window appears
  4. Repeat — it keeps failing, because the migration never completes

How easily this reproduces depends on how quickly the database opens, so slower storage or a larger app.db should make it more likely.

Suggestion

Rather than panicking, commands that reach an uninitialised state could wait for initialisation, or return an error the frontend can retry. The two Attempted to get state before it is initialized messages show the condition is already detected — it just is not survivable right now.

Panic with stack trace (from the systemd journal)
thread 'tokio-rt-worker' (479389) panicked at packages/app-lib/src/event/mod.rs:66:14:
should be initialized when used
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Process 479350 (modrinth-app) of user 1000 dumped core.

Stack trace of thread 479389:
#0  0x00007f3c0aeaf2eb pthread_kill (libc.so.6 + 0xaf2eb)
#1  0x00007f3c0ae44b88 raise (libc.so.6 + 0x44b88)
#2  0x00007f3c0ae257a7 abort (libc.so.6 + 0x257a7)
#3  0x000055a6e3d1b74a n/a (modrinth-app + 0x1c8674a)
#4  0x000055a6e3cf4619 n/a (modrinth-app + 0x1c5f619)
#5  0x000055a6e3d1cca9 n/a (modrinth-app + 0x1c87ca9)
#6  0x000055a6e39fe889 n/a (modrinth-app + 0x1969889)
#7  0x000055a6e3cf4659 n/a (modrinth-app + 0x1c5f659)

Logs

All four runs, scrubbed: authentication codes, account identifiers, username paths and the hostname were replaced with placeholders.

The very first launch — aborts after two log lines (1-crash-first-launch.log)
2026-08-31T09:12:55.047062128+02:00  INFO theseus_gui: Initialized tracing subscriber. Loading Modrinth App!
2026-08-31T09:12:55.053562584+02:00  INFO theseus_gui: Initializing app...
A successful start: 376 ms database open, with the settings migration (2-success-with-settings-migration.log)
2026-08-31T09:45:31.604615701+02:00  INFO theseus_gui: Initialized tracing subscriber. Loading Modrinth App!
2026-08-31T09:45:31.610693068+02:00  INFO theseus_gui: Initializing app...
2026-08-31T09:45:32.105331698+02:00 ERROR get_game_version_tags: theseus::state: Attempted to get state before it is initialized - this should never happen!
2026-08-31T09:45:32.105397232+02:00 ERROR get_loader_tags: theseus::state: Attempted to get state before it is initialized - this should never happen!
2026-08-31T09:45:32.106840342+02:00  INFO initialize_state: theseus_gui: Initializing app event state...
2026-08-31T09:45:32.106892501+02:00  INFO initialize_state: theseus_gui: Initializing app state...
2026-08-31T09:45:32.106901929+02:00  INFO initialize_state:initialize_state{app_identifier="ModrinthApp"}: theseus::state: Connecting to app database
2026-08-31T09:45:32.482177546+02:00  INFO initialize_state:initialize_state{app_identifier="ModrinthApp"}: theseus::state: Fetching app settings
2026-08-31T09:45:32.482272045+02:00  INFO initialize_state:initialize_state{app_identifier="ModrinthApp"}: theseus::state: Initializing directories
2026-08-31T09:45:32.486923644+02:00  INFO initialize_state:initialize_state{app_identifier="ModrinthApp"}: theseus::state: Initializing file watcher
2026-08-31T09:45:32.487619941+02:00  INFO init_watcher: theseus::state::instances::watcher: Initing watcher
2026-08-31T09:45:32.593629807+02:00  INFO theseus_gui::api::utils: opening command None
2026-08-31T09:45:32.613985724+02:00 ERROR theseus_gui::error: error=User is not logged in, no credentials available! span_trace=   0: theseus::api::minecraft_skins::get_available_capes
             at packages/app-lib/src/api/minecraft_skins.rs:265
2026-08-31T09:45:32.699941864+02:00  INFO theseus::state::settings: Migrating settings version 1 to 3
An abort after app.db had grown to 20.7 MB (3-crash-with-20MB-database.log)
2026-09-01T17:12:15.267852802+02:00  INFO theseus_gui: Initialized tracing subscriber. Loading Modrinth App!
2026-09-01T17:12:15.281332286+02:00  INFO theseus_gui: Initializing app...
2026-09-01T17:12:15.862411661+02:00 ERROR get_game_version_tags: theseus::state: Attempted to get state before it is initialized - this should never happen!
2026-09-01T17:12:15.862516889+02:00 ERROR get_loader_tags: theseus::state: Attempted to get state before it is initialized - this should never happen!
A successful start after running VACUUM on app.db (4-success-after-vacuum.log)
2026-09-01T17:21:51.580533027+02:00  INFO theseus_gui: Initialized tracing subscriber. Loading Modrinth App!
2026-09-01T17:21:51.585414440+02:00  INFO theseus_gui: Initializing app...
2026-09-01T17:21:52.033252886+02:00 ERROR get_game_version_tags: theseus::state: Attempted to get state before it is initialized - this should never happen!
2026-09-01T17:21:52.033359927+02:00 ERROR get_loader_tags: theseus::state: Attempted to get state before it is initialized - this should never happen!
2026-09-01T17:21:52.034731290+02:00  INFO initialize_state: theseus_gui: Initializing app event state...
2026-09-01T17:21:52.034771595+02:00  INFO initialize_state: theseus_gui: Initializing app state...
2026-09-01T17:21:52.034777216+02:00  INFO initialize_state:initialize_state{app_identifier="ModrinthApp"}: theseus::state: Connecting to app database
2026-09-01T17:21:52.039756974+02:00  INFO initialize_state:initialize_state{app_identifier="ModrinthApp"}: theseus::state: Fetching app settings
2026-09-01T17:21:52.039848075+02:00  INFO initialize_state:initialize_state{app_identifier="ModrinthApp"}: theseus::state: Initializing directories
2026-09-01T17:21:52.039930991+02:00  INFO initialize_state:initialize_state{app_identifier="ModrinthApp"}: theseus::state: Initializing file watcher
2026-09-01T17:21:52.040007305+02:00  INFO init_watcher: theseus::state::instances::watcher: Initing watcher
2026-09-01T17:21:52.206900332+02:00  INFO theseus_gui::api::utils: opening command None
2026-09-01T17:21:52.684785048+02:00  INFO connect: theseus::state::friends: Connected to friends socket
2026-09-01T17:21:53.243662122+02:00  INFO init_watcher: theseus::state::instances::watcher: World updated: /home/user/.local/share/ModrinthApp/profiles/Fabric 1.21.4/saves/Neue Welt/level.dat
2026-09-01T17:21:53.243952178+02:00  INFO init_watcher: theseus::state::instances::watcher: World updated: /home/user/.local/share/ModrinthApp/profiles/Fabulously Optimized (1)/saves/Neue Welt/level.dat
2026-09-01T17:21:54.249674116+02:00  INFO init_watcher: theseus::state::instances::watcher: World updated: /home/user/.local/share/ModrinthApp/profiles/Fabulously Optimized (1)/saves/Neue Welt/level.dat
2026-09-01T17:21:54.249733578+02:00  INFO init_watcher: theseus::state::instances::watcher: World updated: /home/user/.local/share/ModrinthApp/profiles/Fabric 1.21.4/saves/Neue Welt/level.dat
2026-09-01T17:21:54.249980193+02:00  INFO init_watcher: theseus::state::instances::watcher: World updated: /home/user/.local/share/ModrinthApp/profiles/Fabulously Optimized (1)/saves/Neue Welt/level.dat

I deliberately did not attach the core dumps — they contain full process memory including session tokens — but can produce one privately if that would help.

Activity

  1. inoX-Network commented on Sep 2, 2026

    @inoX-Network
    Author

    How I worked around this for myself in the meantime. Posting it in case it helps other Linux users — not to pre-empt a proper fix, just so I could keep playing while this is open.

    Two steps; the first one alone may already be enough.

    Step 1: shrink the database

    If the app used to start and suddenly doesn't, check how big app.db has become:

    ls -lh ~/.local/share/ModrinthApp/app.db

    Mine had grown to 20.7 MB (5583 rows in the cache table). With the app closed, and after making a copy:

    cp ~/.local/share/ModrinthApp/app.db ~/app.db.backup
    sqlite3 ~/.local/share/ModrinthApp/app.db 'VACUUM;'

    It went down to 18.9 MB and the app then started 8 times in a row. If that solves it for you, you can stop here.

    Step 2: retry automatically when it aborts

    The crash happens within the first seconds, and a second launch almost always wins the race — so a small wrapper is enough.

    It retries only on crash exit codes, and only if the app died quickly. A clean exit, SIGTERM on shutdown or Ctrl+C never trigger a restart, and neither does a crash after hours of use — that would be a different problem, and restarting wouldn't help.

    Create ~/.local/bin/modrinth-start:

    #!/usr/bin/env bash
    MAX_ATTEMPTS=4
    MIN_RUNTIME=20                  # seconds
    CRASH_CODES=(134 139 101)       # SIGABRT, SIGSEGV, Rust panic
    LOG="${XDG_DATA_HOME:-$HOME/.local/share}/ModrinthApp/starter.log"
    
    mkdir -p "$(dirname "$LOG")"
    
    is_crash() {
        local code=$1
        for c in "${CRASH_CODES[@]}"; do
            [[ $code -eq $c ]] && return 0
        done
        return 1
    }
    
    for (( attempt=1; attempt<=MAX_ATTEMPTS; attempt++ )); do
        start=$SECONDS
        /usr/bin/modrinth-app "$@"
        code=$?
        runtime=$(( SECONDS - start ))
    
        if ! is_crash "$code"; then
            [[ $attempt -gt 1 ]] && echo "$(date '+%F %T')  started on attempt $attempt" >> "$LOG"
            exit $code
        fi
    
        if [[ $runtime -ge $MIN_RUNTIME ]]; then
            echo "$(date '+%F %T')  crashed after ${runtime}s (code $code) - not a startup problem, not retrying" >> "$LOG"
            exit $code
        fi
    
        echo "$(date '+%F %T')  attempt $attempt: crashed after ${runtime}s (code $code) - retrying" >> "$LOG"
        sleep 2
    done
    
    echo "$(date '+%F %T')  gave up after $MAX_ATTEMPTS attempts" >> "$LOG"
    command -v notify-send >/dev/null && notify-send -u critical \
        "Modrinth won't start" "Four attempts failed. Details: $LOG"
    exit 1

    Then make it executable and point your desktop entry at it:

    chmod +x ~/.local/bin/modrinth-start
    mkdir -p ~/.local/share/applications
    cp /usr/share/applications/modrinth-app.desktop ~/.local/share/applications/
    sed -i "s|^Exec=.*|Exec=$HOME/.local/bin/modrinth-start %u|" \
        ~/.local/share/applications/modrinth-app.desktop
    update-desktop-database ~/.local/share/applications 2>/dev/null || true

    Adjust the path to modrinth-app if your distribution installs it elsewhere. A log of every retry ends up in ~/.local/share/ModrinthApp/starter.log, so you can tell whether it is still happening.

    Removing it again

    Please do remove it once this is fixed upstream — the copied desktop entry permanently shadows the system one, so it won't pick up a changed Exec line or new MIME types (URL schemes, for instance) from a future update.

    rm ~/.local/bin/modrinth-start
    rm ~/.local/share/applications/modrinth-app.desktop
    update-desktop-database ~/.local/share/applications 2>/dev/null || true

    That restores the packaged launcher; nothing else is touched. The VACUUM from step 1 needs no undoing — it only compacted the database.

  2. inoX-Network commented on Oct 14, 2026

    @inoX-Network
    Author

    Update: this no longer reproduces for me. I updated from 0.18.0 to 0.19.2 on Sep 11 and later to 0.21.4 and 0.21.9 (Arch, pacman package).

    My launcher wrapper logs every crash on startup: the last ones were on Sep 2 and Sep 7 (exit code 134), both on 0.18.0. Since the update there have been 26 game launches across 0.19.2 and 0.21.4 with no crash, no core dump, and nothing in the wrapper log. Four quick cold starts on 0.21.9 today were clean as well.

    Looks like this was fixed in 0.19.x. Closing. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions