can1357/oh-my-pi · error · AIError.ConfigurationError

Antigravity credentials missing projectId

Error message

Antigravity credentials missing projectId

What it means

Antigravity (Google) OAuth credentials must include a projectId because token refresh calls refreshAntigravityToken(refresh, projectId) — the project scopes the token exchange against Google's endpoints. When stored credentials lack projectId, the registry's refreshToken hook throws this ConfigurationError before attempting the refresh. The login flow normally populates projectId, so its absence means incomplete or legacy credentials.

Source

Thrown at packages/ai/src/registry/google-antigravity.ts:15

import * as AIError from "../error";
import type { OAuthCredentials, OAuthLoginCallbacks } from "./oauth/types";
import type { ProviderDefinition } from "./types";

export const googleAntigravityProvider = {
	id: "google-antigravity",
	name: "Antigravity (Gemini 3, Claude, GPT-OSS)",
	login: async (cb: OAuthLoginCallbacks) => {
		// Lazy import: keep heavy OAuth flow modules out of the eager registry graph.
		const { loginAntigravity } = await import("./oauth/google-antigravity");
		return loginAntigravity(cb);
	},
	refreshToken: async (credentials: OAuthCredentials) => {
		if (!credentials.projectId) {
			throw new AIError.ConfigurationError("Antigravity credentials missing projectId");
		}
		const { refreshAntigravityToken } = await import("./oauth/google-antigravity");
		return refreshAntigravityToken(credentials.refresh, credentials.projectId);
	},
	callbackPort: 51121,
	pasteCodeFlow: true,
} as const satisfies ProviderDefinition;

View on GitHub (pinned to 9690622007)

Solutions

  1. Delete the stored Antigravity credentials and re-run the login flow (loginAntigravity) so projectId is captured.
  2. Manually add the correct projectId to the stored credentials object if you know it.
  3. Check the stored auth file location (e.g. ~/.config omp auth state) for a missing or null projectId field.
  4. Update the library/flow version so login and refresh agree on the credentials schema.

Example fix

// before
await registry.refreshToken({ refresh: "token", projectId: undefined });
// throws ConfigurationError
// after (re-login to capture projectId)
const creds = await registry.login(callbacks); // includes projectId
await registry.refreshToken(creds);
Defensive patterns

Strategy: try-catch

Validate before calling

// before triggering a refresh
if (!credentials.projectId) {
  await reloginAntigravity(); // recapture full credentials including projectId
}

Type guard

function hasProjectId(c: OAuthCredentials): c is OAuthCredentials & { projectId: string } {
  return typeof c.projectId === "string" && c.projectId.length > 0;
}

Try / catch

try {
  await registry.refreshToken(credentials);
} catch (err) {
  if (err instanceof AIError.ConfigurationError && /missing projectId/.test(err.message)) {
    credentials = await registry.login(callbacks); // re-login to rebuild credentials
    await registry.refreshToken(credentials);
  } else throw err;
}

Prevention

When it happens

Trigger: Calling the registry's refreshToken (or any path that triggers token refresh) with OAuthCredentials whose projectId field is null/undefined — typically credentials written by an older login flow, hand-crafted credentials, or a partially migrated auth.json.

Common situations: Credentials created before projectId became required; manually editing or truncating the stored auth file; syncing credentials across machines with different code versions; programmatically constructing OAuthCredentials without projectId.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/180ae2884dabc191. Report an issue: GitHub.