Skip to content

[Bug]: T3 Code opens a blank window when the Linux credential store is locked #9239

Open
selenodot/t3code
#2

Description

@eliesgalvira

What happened

After updating the Linux AppImage from stable 0.0.35 to
0.0.36-nightly.20260827.1207,
T3 Code opened a completely black window that could not be resized. The splash
screen sometimes appeared first. No authentication prompt appeared anywhere in
the reporter's Niri session. The black window was the only visible symptom.

This is the first affected build observed. Stable 0.0.35 was not tested with
the credential store locked, so it is not a confirmed working baseline for this
condition.

Unlocking the native credential store made the same AppImage start normally.

An authentication prompt appeared later in an isolated Xvfb/Openbox test.
While the prompt remained open, the T3 window stalled. Dismissing it allowed T3
to show Primary environment request failed during fetch-session-state (HTTP 500). The prompt never appeared during the original failure.

Expected: T3 Code may wait for the credential store to be unlocked, but its
window should remain responsive. It should show the authentication request or
a recoverable error.

Actual: T3 Code opens a black, non-resizable window with no explanation of what
it is waiting for.

Area: apps/desktop

Impact: Blocks work completely

Diagnosis

T3 Code is waiting on the locked credential store during startup. We reproduced
this on the current nightly with three different Linux credential providers.
Unlocking each store made the project picker load. Bypassing encrypted storage
with --password-store=basic also made it load.

The tests identify the failing boundary, but not the exact T3, Clerk, or
Electron call that waits for the store.

Steps to reproduce

  1. Start a Linux desktop session with its native credential store locked. In
    the original case, the credential-store service restarted after login and no
    longer had the password supplied by PAM.
  2. Launch the T3 Code AppImage.
  3. Observe that T3 opens a black, non-resizable window. No authentication prompt
    appears.
  4. Unlock the credential store, close T3 Code, and launch the same AppImage.
  5. Observe that the project picker loads normally.

The same locked-versus-unlocked test ran in three separate, pinned NixOS VMs:

Credential provider in test VM Locked Unlocked
GNOME Keyring 50.0 window opens; UI does not load within 5 seconds project picker loads
KeePassXC 2.7.12 window opens; UI does not load within 5 seconds project picker loads
KDE KWallet 6.29.0 window opens; UI does not load within 5 seconds project picker loads

These provider names describe disposable test VMs, not the reporter's host.
GNOME Keyring and KeePassXC use the freedesktop Secret Service API in these
tests. KWallet uses Chromium's separate KWallet integration.

The five-second cutoff detects the startup stall. It does not claim that every
provider waits forever. One exploratory KeePassXC run recovered after about 25
to 30 seconds.

Version

0.0.39-nightly.20260902.1257,
commit 70cd258d8aac43ea57494527b00bf36de3efa6c0.

AppImage SHA-256:
a8fa9413b6aa7bde3f5ad7c94def29f6aafaaac3f185f7d14f47eef60550e929

Environment

Reporter: Linux x86_64, Niri on Wayland, AppImage, native encrypted credential
store.

Validation: pinned NixOS VMs, Linux 6.18.46, Xvfb/Openbox. The tests use the
extracted, hash-pinned AppImage, so they do not cover Niri/Wayland or the FUSE
mount path.

Evidence

locked:   app ready -> safe storage ready -> main window created -> UI probe timed out
unlocked: renderer ready -> "Add project"
basic:    renderer ready -> "Add project"

One isolated test also recorded an authentication prompt starting before the
timeout. After that prompt was dismissed, T3 displayed:

Something went wrong.
Primary environment request failed during fetch-session-state (HTTP 500).
PrimaryEnvironmentRequestError

The screenshot shows this post-dismissal error. During the original failure,
the prompt never appeared and the window remained completely black.

Related issues

  • #3513 covers the same
    post-failure session-state error and its poor recovery. This report adds a
    specific trigger, a locked credential store, and the black window that appears
    before the error.
  • #5427,
    #2539,
    #2880, and
    #7689 cover missing or
    unavailable secure storage. Here T3 selects an encrypted credential store,
    but that store is locked.

Fix applied or workaround

Unlocking the credential store restores startup. Logging out and back in can
unlock it through PAM when that integration is configured.

--password-store=basic avoids the stall but stores credentials without native
encryption. It is useful as a diagnostic, not as a safe default.

Filed by

OpenAI Codex (gpt-5.6-sol) via t3 triage.

Activity

  1. changed the title [-]T3 Code opens a blank window when the Linux credential store is locked[/-] [+][Bug]: T3 Code opens a blank window when the Linux credential store is locked[/+] on Sep 2, 2026
  2. selenodot commented on Sep 2, 2026

    @selenodot

    Investigating this issue

  3. eliesgalvira commented on Sep 2, 2026

    @eliesgalvira
    Author

    @selenodot One additional finding may help with the next version of the fix.

    0.0.28nightly.20260619.598 (20f37f) remains responsive with the credential store locked. The immediately following nightly, 0.0.28nightly.20260619.602 (3e01c4), freezes. The only intervening change was “Migrate desktop auth to Clerk bridge” (#3092).

    Instrumentation of the affected build stopped in the Clerk tokencache save path:

    storage.setItem() → resolveCipher() → safeStorage.isEncryptionAvailable()

    Both mainprocess and renderer heartbeats stopped at that call.

    Current T3 Code also reaches the same blocking API through the connectioncatalog path, so the general diagnosis in #9246 is sound. The narrower conclusion is that Clerk was the historical caller at the firstbad release boundary, while the connection catalog is another current caller of the same synchronous API.

  4. solomonneas commented on Sep 5, 2026

    @solomonneas

    Additional occurrence on Ubuntu 24.04.4 LTS, Linux x86_64, using the T3 Code AppImage and the gnome_libsecret backend on September 5.

    The window rendered an empty project sidebar and then showed Still connecting / T3 Code could not confirm this workspace. Existing projects were inaccessible. Repeated application launches did not recover it. A host reboot restored catalog reads and the project list.

    The retained desktop.trace.ndjson files provide this sequence. Times are UTC, and durations are from completed spans:

    2026-09-05 13:15:35.135  desktop.startup                     Success, 184.464956 ms
    2026-09-05 13:24:50.884  desktop.startup                     Success, 151.684467 ms
                           no completed connectionCatalogStore.get span in this interval
    2026-09-05 13:28:20.084  desktop.startup                     Success, 172.028966 ms
    2026-09-05 13:28:22.973  desktop.connectionCatalogStore.get  Success, 29.119375 ms
    2026-09-05 17:10:49.494  desktop.connectionCatalogStore.get  Success, 25.580452 ms
    

    Startup reported safe storage ready with backend=gnome_libsecret. The recovered desktop was 0.0.39-nightly.20260905.1288. Several nightly builds were used during recovery, so that version is a recovery reference, not a confirmed first affected version.

    This supports the startup/catalog boundary described here. I did not capture a native stack during the stall or establish whether the credential store was locked, so I cannot independently identify the exact blocking call. The symptom on this host was a rendered but unusable shell rather than a completely black window. I do not have a deterministic reproduction on this host after reboot.

    The preservation concern raised on #9246 matters for a follow-up fix: a temporary secure-storage timeout must not turn an unread catalog into an empty catalog that is later persisted over the original. A recovery test should start with a populated encrypted catalog, make secure storage unavailable, then restore it and verify that the saved environments and credentials survive.

  5. juliusmarminge commented on Oct 22, 2026

    @juliusmarminge
    Member

    Triaged as a desktop startup bug. Checked current main at 07d38b8d17: native credential-store operations remain synchronous in ElectronSafeStorage. This is source inspection, not a reproduction. This Linux host has no Electron executable, Xvfb, or GNOME Keyring daemon, so the locked/unlocked AppImage comparison could not be run. No duplicate was identified among the 944 open issues; no PR is linked to this issue. Leaving open for maintainer investigation because changes to credential handling require maintainer review under the automated triage policy.

  6. juliusmarminge commented on Oct 22, 2026

    @juliusmarminge
    Member

    Existing work found in #17311: it switches the Electron safe-storage adapter to the async provider and explicitly requires human approval for credential-storage changes. Its native Linux keystore/startup behavior remains unverified, so it is a candidate fix for this report, not a confirmed resolution. No duplicate PR opened. This issue should remain open until the locked/unlocked Linux comparison is verified.

  7. juliusmarminge commented on Oct 22, 2026

    @juliusmarminge
    Member

    Reproduced on current main 96bae5465b with the real Electron desktop on Ubuntu 24.04, Xvfb/Openbox and GNOME Keyring 46.1 in an isolated D-Bus session. An unlocked login collection loaded onboarding within 12 seconds. Locking that same collection before relaunch stalled startup on the splash while the native unlock prompt remained open; SIGTERM did not exit the stalled main process. This verifies the prompt-visible variant; Niri/Wayland and the AppImage mount path were not tested. Existing #17311 is being preserved.

  8. adamczhang commented on Nov 4, 2026

    @adamczhang

    Additional occurrence: GDM auto-login on Ubuntu 26.04, with the app reporting "not responding" after a reboot

    This reproduces on a real GNOME Wayland desktop using the .deb nightly. The trigger is ordinary GDM auto-login, so this may affect any Linux user with auto-login enabled, not only setups where the keyring service restarts after login.

    What happened

    After a reboot, T3 Code opened but GNOME showed "T3 Code (Nightly) is not responding". The window stayed unusable across three launches, one from autostart and two from the app menu. Unlocking the default keyring fixed it without any other change to T3 Code.

    Why auto-login triggers it

    GDM has no password to pass to PAM during auto-login, so the journal shows this at every login:

    gkr-pam: no password is available for user
    gkr-pam: couldn't unlock the login keyring.
    

    On this machine, the default alias points to a separate collection, Default_Keyring, which is also locked at boot.

    Evidence

    • Electron selected gnome_libsecret. All three failed launches logged up to registered URL scheme handler, but none logged backend ready.
    • The backend itself was healthy on all the checks I ran. server.startup completed on the autostart launch. On the third launch, port 3773 answered /.well-known/t3/environment.
    • The local window never connected. The trace has no 127.0.0.1 Electron requests for those launches, although other devices on the LAN connected to the same backend normally.
    • desktop.trace.ndjson wasn't written at all during those launches.
    • The processes were idle rather than spinning, with no CPU growth over a 6-second sample and no threads in D state.
    • The keyring daemon had 5 /org/freedesktop/secrets/prompt/* objects outstanding. I didn't establish whether any of them had ever been displayed.
    • gh auth status hung and the Passwords app (seahorse) appeared hung at the same time. Trace spans also show gh credential lookups timing out at startup, so the locked keyring affects more than T3 Code here.

    Comparison on the same build

    State Result
    Launch before the reboot backend ready about 1 second after start, local window connected
    After reboot, keyring locked (3 launches) no backend ready, "not responding"
    Keyring daemon restarted, Default_Keyring unlocked backend ready about 1 second after start, local window connected, gh working again

    Recovery that worked

    1. Quit T3 Code and seahorse.
    2. Run systemctl --user restart gnome-keyring-daemon.service, which cleared the outstanding prompts.
    3. Call Secret Service Unlock and Prompt from a single process that stays connected. Separate gdbus calls fail, because the prompt object is gone by the time the second call runs.
    4. Enter the password in the GNOME dialog, then relaunch T3 Code.

    Not verified

    Source check

    ElectronSafeStorage.ts still calls the synchronous safeStorage methods on v0.1.7-nightly.20261103.4106, v0.1.7-nightly.20261104.4151 and main as of 2026-11-04 UTC, so updating isn't expected to help yet.

    Environment

    • T3 Code desktop 0.1.7-nightly.20261103.4106 (commit e1e520c9), .deb install, Electron 44.10.0
    • Ubuntu 26.04.1 LTS, kernel 7.0.0-42, GNOME Shell 50.1 on Wayland
    • gnome-keyring 50.0, gdm3 50.1, with AutomaticLoginEnable=true
    • Triage CLI: 0.1.6 (this is the version of the t3 CLI, not the build the bug happened on)

    Related: #23823, #17311

    Produced with t3 triage using Claude Code (Claude Opus 5.5), and reviewed by the reporter before posting.

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