[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:
- 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. - 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.
- 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:
- A new process starts, checks
app.requestSingleInstanceLock(), sees the running background instance, sends the'second-instance'event, and immediately callsapp.quit(); process.exit(0);. - 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:
Execlacks the%uURL placeholder. When Chrome/Firefox callsantigravity://auth?token=..., Fedora’s desktop launcher runsantigravity --no-sandboxand 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 forantigravity-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 viaoauth2.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)
"