[BUG & ROOT CAUSE] Linux/Fedora: Silent Launch Failure on Re-open (0-Window second-instance) & Auth Deep-Link Loop

[BUG & ROOT CAUSE ANALYSIS] Antigravity & IDE on Linux (Fedora): Silent Launch Failure on Re-open & Deep-Link Auth Loop

Category: Antigravity / Linux / Bug Report
Target Environment: Fedora 40/41/42/44 (GNOME Shell, Wayland), Arch Linux, Ubuntu (Wayland)
Affected Applications: Google Antigravity 2.0 (v2.8.1+) & Antigravity IDE


Executive Summary

On Linux distributions (especially Fedora Workstation using GNOME on Wayland), users encounter two severe, recurring issues when installing via the standalone Linux tarball:

  1. Silent Failure to Launch After Closing: When the user closes the Antigravity window and attempts to launch it again, nothing happens—no window appears, and no error is displayed. Launching only works after manually running pkill -9 -f antigravity.
  2. Deep-Link Authentication Loop: During initial sign-in, the browser successfully authenticates with Google, but the application never receives the callback token and remains stuck on the “Sign in with Google” / loading screen.
  3. Offline Launch Demands Login: Launching without an active internet connection causes an immediate unauthenticated state rather than preserving offline session cache.

We inspected the decompiled Electron bundle (app.asar), system logs, and .desktop configuration files. Below is the exact architectural root cause and the upstream patches to fix both issues.


System Environment

  • OS: Fedora Linux 44 (Workstation Edition) / GNOME 47+ (Wayland)
  • Application: Google Antigravity 2.0 (v2.8.1) / Antigravity IDE
  • Installation: Standalone Linux tarball (/opt/antigravity/antigravity-x64/ and /opt/antigravity/antigravity-ide/)
  • Display Server: Wayland (with --no-sandbox)

Root Cause Analysis 1: The 0-Window second-instance Bug on Linux

1. RUN_IN_BACKGROUND defaults to true on Linux

In Antigravity’s bundle (app.asar), default settings are initialized as:

[SettingKey.RUN_IN_BACKGROUND, process.platform !== 'win32'],

On Windows, runInBackground is false. On Linux and macOS, it defaults to true.

2. window-all-closed does not quit the application

electron.app.on('window-all-closed', async () => {
    if (isQuitting || !hasStartedMainApplication) return;
    const runInBackground = await settingsService.getSetting('runInBackground');
    if (!runInBackground) {
        electron.app.quit();
    } else {
        electron.app.dock?.hide(); // macOS-only API, no-op on Linux!
    }
});

When a Linux user closes all windows, electron.app.quit() is never called. All windows are destroyed (BrowserWindow.getAllWindows().length === 0), but the main process, zygote processes, and language_server continue running silently in the background.

Furthermore, stock GNOME Shell does not provide a system tray (AppIndicator) out of the box, meaning the user has no visual clue that Antigravity is still running.

3. The second-instance handler fails when wins.length === 0

When the user clicks the Antigravity launcher again:

  1. A new process starts, checks app.requestSingleInstanceLock(), sees the running background instance, sends the 'second-instance' event, and immediately calls app.quit(); process.exit(0);.
  2. The running background process receives 'second-instance':
electron.app.on('second-instance', (event, commandLine) => {
    const wins = electron.BrowserWindow.getAllWindows();
    if (wins.length > 0) {
        if (wins[0].isMinimized()) wins[0].restore();
        wins[0].show();
        wins[0].focus();
        electron.app.focus({ steal: true });
    }
    const url = commandLine.find((arg) => arg.startsWith(`${PROTOCOL}://`));
    if (url) handleDeepLink(url);
});

Notice the flaw: The code only restores a window if (wins.length > 0).
Because all windows were closed earlier, wins.length is 0. There is no fallback to open or create a window when wins.length === 0 (that logic was only attached to macOS’s 'activate' Dock event!).

Result: The background process does nothing, the newly launched process has already exited, and Antigravity completely refuses to appear on screen.


Root Cause Analysis 2: Dropped OAuth Callback Token (Missing %u / %F)

In standalone tarball extractions, the desktop launcher entries generated for Linux are missing FreeDesktop MIME spec arguments:

For Antigravity:

[Desktop Entry]
Name=Antigravity
Exec=antigravity --no-sandbox
Icon=/opt/antigravity/antigravity-x64/resources/assets/icon.png
MimeType=x-scheme-handler/antigravity;
  • Flaw: Exec lacks the %u URL placeholder. When Chrome/Firefox calls antigravity://auth?token=..., Fedora’s desktop launcher runs antigravity --no-sandbox and strips the callback URL entirely. The app receives no token.

For Antigravity IDE:

[Desktop Entry]
Name=Antigravity IDE
Exec=antigravity-ide --no-sandbox
Icon=/opt/antigravity/antigravity-ide/resources/assets/icon.png
  • Flaw: It completely lacks MimeType=x-scheme-handler/antigravity-ide; and %F. The system has no registered protocol handler for antigravity-ide://.

Root Cause Analysis 3: Corrupted Local State on Offline Startup

  • Google OAuth tokens expire after 60 minutes.
  • On boot, language_server (auth_provider.go) attempts an immediate token refresh via oauth2.googleapis.com.
  • When offline, DNS/connection fails (dial tcp: lookup oauth2.googleapis.com: no such host).
  • The client catches this network error and resets auth state to unauthenticated, corrupting the local session in ~/.config/Antigravity/ and forcing a login prompt while offline.

Recommended Upstream Fix for the Antigravity Team

1. In second-instance handler:

Add a fallback to reopen the window when wins.length === 0:

electron.app.on('second-instance', (event, commandLine) => {
    const wins = electron.BrowserWindow.getAllWindows();
    if (wins.length > 0) {
        if (wins[0].isMinimized()) wins[0].restore();
        wins[0].show();
        wins[0].focus();
        electron.app.focus({ steal: true });
    } else {
        // Fix for Linux: Recreate the window if app was running headless
        openMainWindow();
    }
    const url = commandLine.find((arg) => arg.startsWith(`${PROTOCOL}://`));
    if (url) handleDeepLink(url);
});

2. Platform default for RUN_IN_BACKGROUND:

On Linux platforms where desktop environments (like GNOME) may not support StatusNotifierItem by default, set runInBackground to false unless a supported tray is detected:

[SettingKey.RUN_IN_BACKGROUND, process.platform === 'darwin'],

3. Update Official .desktop Templates:

Ensure .desktop templates include URL placeholders and MIME types:

  • Antigravity:
    Exec=antigravity --no-sandbox %u
    MimeType=x-scheme-handler/antigravity;
    
  • Antigravity IDE:
    Exec=antigravity-ide --no-sandbox %F
    MimeType=x-scheme-handler/antigravity-ide;text/plain;inode/directory;
    

Workaround for Linux / Fedora Users

For any users experiencing this right now:

# 1. Update ~/.local/share/applications/antigravity.desktop
sed -i 's|Exec=antigravity --no-sandbox.*|Exec=antigravity --no-sandbox %u|' ~/.local/share/applications/antigravity.desktop
echo "MimeType=x-scheme-handler/antigravity;" >> ~/.local/share/applications/antigravity.desktop

# 2. Update ~/.local/share/applications/antigravity-ide.desktop
sed -i 's|Exec=antigravity-ide --no-sandbox.*|Exec=antigravity-ide --no-sandbox %F|' ~/.local/share/applications/antigravity-ide.desktop
echo "MimeType=x-scheme-handler/antigravity-ide;text/plain;inode/directory;" >> ~/.local/share/applications/antigravity-ide.desktop

# 3. Register protocol handlers
update-desktop-database ~/.local/share/applications/
xdg-mime default antigravity.desktop x-scheme-handler/antigravity
xdg-mime default antigravity-ide.desktop x-scheme-handler/antigravity-ide

# 4. Disable runInBackground to prevent zombie processes on close
python3 -c "
import json, os
p = os.path.expanduser('~/.config/Antigravity/app_storage.json')
d = json.load(open(p)) if os.path.exists(p) else {}
d['runInBackground'] = 'false'
json.dump(d, open(p, 'w'), indent=2)
"

Hi @mrxsierra ,

Could you please update to the latest version and let us know if the issue is resolved or if it still persists?

Hi @Ambati_Rajendra,

Thank you for following up!

I updated to v2.16.0 on Fedora Workstation (GNOME / Wayland) and verified the following:

:white_check_mark: Verified Fixes in v2.16.0:

  1. 0-Window Re-open / Second-Instance: Closing the window and re-launching now reliably re-opens the window (showOrCreateWindow correctly handles the headless state). Manual pkill is no longer needed.
  2. Browser Sign-In Callback: The OAuth callback flow and disconnect handling during sign-in are significantly smoother and no longer enter permanent failure loops.

:magnifying_glass_tilted_left: Minor Edge-Case Observed (Offline State Machine):

During testing, I observed one related authentication edge-case when launching without an active internet connection:

  • Symptom: If Antigravity is opened offline, the app immediately displays the “Sign in” screen rather than preserving the cached offline workspace session.
  • Behavior on Reconnect: When the internet connection is restored, the application does not automatically detect connectivity or re-validate the cached session (the screen remains on the sign-in prompt).
  • Workaround: Closing and re-opening the application once online immediately restores the logged-in session without requiring re-authentication (confirming the local token cache in ~/.config/Antigravity/ remains intact).

It appears network failure on startup might be misclassified by the client as an unauthenticated state rather than an offline mode.

Overall, the core Linux silent-launch and second-instance regressions are fully resolved in v2.16.0. Appreciate the rapid work by the team!