{"record":{"id":"651a0831a782cd36","repo":"decolua/9router","slug":"no-project-id-found-in-response","errorCode":null,"errorMessage":"No project ID found in response","messagePattern":"No project ID found in response","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/lib/oauth/services/gemini.js","lineNumber":99,"sourceCode":"    );\n\n    if (!response.ok) {\n      const error = await response.text();\n      throw new Error(`Failed to fetch project ID: ${error}`);\n    }\n\n    const data = await response.json();\n\n    // Extract project ID\n    let projectId = \"\";\n    if (typeof data.cloudaicompanionProject === \"string\") {\n      projectId = data.cloudaicompanionProject.trim();\n    } else if (data.cloudaicompanionProject?.id) {\n      projectId = data.cloudaicompanionProject.id.trim();\n    }\n\n    if (!projectId) {\n      throw new Error(\"No project ID found in response\");\n    }\n\n    return projectId;\n  }\n\n  /**\n   * Get user info from Google\n   */\n  async getUserInfo(accessToken) {\n    const response = await fetch(`${this.config.userInfoUrl}?alt=json`, {\n      headers: {\n        Authorization: `Bearer ${accessToken}`,\n        Accept: \"application/json\",\n      },\n    });\n\n    if (!response.ok) {\n      const error = await response.text();","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/src/lib/oauth/services/gemini.js#L81-L117","documentation":"GeminiCLIService.fetchProjectId() (src/lib/oauth/services/gemini.js:99) treats the loadCodeAssist response as successful only if it can extract a non-empty cloudaicompanionProject — either a plain string or an object with an .id. When the 2xx response contains neither (or an empty/whitespace string), the library throws, because saving tokens without a project ID would leave the Gemini CLI provider unusable.","triggerScenarios":"fetchProjectId(accessToken) returns 200 but data.cloudaicompanionProject is undefined, empty string, or whitespace-only — e.g. the account has never provisioned a Code Assist project, the API returned a tier/onboarding-only payload (currentTier with no project), or Google altered the response schema.","commonSituations":"Brand-new Google accounts with no auto-provisioned cloudaicompanionProject yet; Workspace accounts where admin policy blocks auto-provisioning; users in regions where onboarding is incomplete; the internal API changed shape so the field moved/renamed.","solutions":["Log the full response JSON from loadCodeAssist to see what fields are actually returned.","Ensure the Google account has Gemini Code Assist enabled/onboarded (visit the Code Assist onboarding in AI Studio / Cloud Console) and retry.","Try authorizing with a personal (non-Workspace) Google account, which auto-provisions a project more reliably.","If data shows a new schema (e.g. project under a different key), update the extraction logic in fetchProjectId.","Wait and retry — auto-provisioning can lag minutes behind first consent."],"exampleFix":"// before\nif (!projectId) {\n  throw new Error(\"No project ID found in response\");\n}\n// after\nif (!projectId) {\n  const tier = data.currentTier || data.allowedTiers;\n  throw new Error(`No project ID in loadCodeAssist response (tier=${JSON.stringify(tier)}). Onboard the account to Gemini Code Assist, then re-run connect().`);\n}","handlingStrategy":"validation","validationCode":"// shape-check the loadCodeAssist payload before relying on it\nconst data = await response.json();\nconst proj = data.cloudaicompanionProject;\nconst ok = typeof proj === \"string\" ? proj.trim().length > 0 : !!(proj && typeof proj.id === \"string\" && proj.id.trim());\nif (!ok) console.error(\"No cloudaicompanionProject in response; account may not be onboarded to Code Assist.\", JSON.stringify(data).slice(0, 500));","typeGuard":"function extractProjectId(data) {\n  const p = data?.cloudaicompanionProject;\n  if (typeof p === \"string\" && p.trim()) return p.trim();\n  if (p && typeof p.id === \"string\" && p.id.trim()) return p.id.trim();\n  return null;\n}","tryCatchPattern":"try {\n  const projectId = await geminiService.fetchProjectId(tokens.access_token);\n} catch (err) {\n  if (err.message === \"No project ID found in response\") {\n    console.error(\"Your Google account has no Code Assist project yet. Onboard at the Gemini Code Assist console, or retry with a personal account.\");\n  } else throw err;\n}","preventionTips":["Onboard the Google account to Gemini Code Assist before running connect().","Prefer personal Google accounts; Workspace policies often block auto-provisioning.","Log the raw loadCodeAssist payload when debugging so schema changes are visible.","Allow a few minutes after first consent for project auto-provisioning, then retry."],"tags":["gemini","google-cloud","response-parsing","project-id","oauth"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}