Repository navigation
Conversation
On macOS, createNativeCredentialEntry called
Entry.withTarget('gemini:antigravity', ...). The macOS keyring backend only
accepts a keychain kind (User / System / Common / Dynamic) as the target, so
constructing the entry threw "Value of 'keychain' is invalid", which was
classified as CredentialStoreReadError('unavailable'). Every cloud account
switch on macOS failed with "The Antigravity credential store is unavailable"
(diagnostic kind target-write-failed).
Only macOS and Linux reach the native keyring (Windows uses its own credential
target), so use the default builder new Entry('gemini', 'antigravity') on both,
matching OpenCodeNativeCredentialStore.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
🔵 Needs a closer look
It modifies credential-storage behavior, a high-risk surface, and the full packaged-app macOS account switch remains unverified, so human review is warranted.
0 open findings
What changed in this PR
This PR fixes a macOS-only bug in the Antigravity cloud-account credential flow. createNativeCredentialEntry previously built the native keyring entry with Entry.withTarget('gemini:antigravity', 'gemini', 'antigravity') on every non-Linux platform. On macOS, @napi-rs/keyring interprets the first argument as a keychain kind (User/System/Common/Dynamic), so the entry could not be constructed at all, surfacing as CredentialStoreReadError: unavailable and a failed account switch. Windows never reaches this helper (it reads/writes via windowsCredentialStore), so the broken branch only ever ran on macOS. The fix uses the default new Entry('gemini', 'antigravity') builder on all platforms that reach the native keyring, matching the pattern already documented in OpenCodeNativeCredentialStore.
Changes:
- Replace the platform-conditional
Entry.withTarget(...)with the defaultnew Entry('gemini', 'antigravity')builder increateNativeCredentialEntry. - Update the explanatory comment to describe why the credential target must not be passed to
Entry.withTarget. - Extend the macOS read unit test to assert the entry is built without a target and that
withTargetis never called, catching the regression.
| File | Description |
|---|---|
| src/modules/antigravity-runtime/credentials/antigravityCredentialStore.ts | Builds the native keyring entry with the default new Entry(service, account) constructor instead of Entry.withTarget, fixing macOS reads/writes. |
| src/tests/unit/antigravity-credential-store-read.test.ts | Adds assertions to the macOS case verifying the entry is created with ('gemini', 'antigravity') and withTarget is not invoked. |
I verified the fix against the surrounding code: both the read path (win32 returns at readAntigravityCredentialStoreToken before readViaNativeKeyring) and the write path (win32 returns in writeToSystemCredentialStore before writeViaNativeKeyring) confirm Windows never reaches createNativeCredentialEntry, so dropping withTarget is safe. The new assertions mirror the existing Linux test (antigravity-credential-store-read.test.ts:227-228), and no test expects withTarget to be called. I found no additional issues to flag.
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
Closing: this fixes the macOS keychain read, but the account switch still fails because of further problems in the write path. Details are in #351. |
Problem
On macOS, every cloud account switch fails with:
The log shows
CredentialStoreReadError: The Antigravity credential store is unavailable.(storage: credential-store,errorCode: unavailable). Reproduced on v0.23.0 and v0.25.1, macOS arm64, with a validgemini/antigravityitem in the login keychain.Root cause
createNativeCredentialEntryinsrc/modules/antigravity-runtime/credentials/antigravityCredentialStore.tscallsEntry.withTarget('gemini:antigravity', 'gemini', 'antigravity')on every non-Linux platform. The macOS backend of@napi-rs/keyringonly accepts a keychain kind as the target, so the entry cannot even be constructed:classifyCredentialStoreReadErrormaps that tounavailable. Windows never reaches this function (it reads and writes throughwindowsCredentialStore), so thewithTargetbranch only ever ran on macOS, where it always fails. The existing unit test did not catch it because thewithTargetmock accepts any target.OpenCodeNativeCredentialStorealready documents this exact pitfall.Fix
Use the default builder,
new Entry('gemini', 'antigravity'), on both macOS and Linux. The macOS unit test now asserts the entry is built without a target. That assertion fails onmainand passes with this change.Verification
npx vitest run src/tests/unit/antigravity-credential-store-read.test.ts: 9/9 pass (the macOS case fails without the fix).tsc --noEmitare clean on the changed files.keyring.darwin-arm64.nodefrom v0.25.1 against the real login keychain:withTarget('gemini:antigravity', …)throws the error above;new Entry('gemini', 'antigravity').getSecret()returns the storedgo-keyring-base64:payload.writeAntigravityCredentialStoreTokentests insecurity-migration.test.ts(Windows write paths) fail on macOS onmaintoo (koffiimport), with or without this change.🤖 Generated with Claude Code