{"record":{"id":"38265efafbae308f","repo":"decolua/9router","slug":"onboarduser-done-but-no-project-id-in-response","errorCode":null,"errorMessage":"onboardUser done but no project_id in response","messagePattern":"onboardUser done but no project_id in response","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"open-sse/services/projectId.js","lineNumber":241,"sourceCode":"                signal: localCtrl.signal\n            });\n\n            clearTimeout(timeoutId);\n\n            if (!response.ok) {\n                const errorText = await response.text().catch(() => \"\");\n                throw new Error(`onboardUser HTTP ${response.status}: ${errorText.slice(0, 200)}`);\n            }\n\n            const data = await response.json();\n\n            if (data.done === true) {\n                const projectId = extractProjectIdFromOnboard(data);\n                if (projectId) {\n                    console.log(`[ProjectId] Successfully onboarded, project ID: ${projectId}`);\n                    return projectId;\n                }\n                throw new Error(\"onboardUser done but no project_id in response\");\n            }\n\n            // Server not done yet – wait and retry\n            console.log(`[ProjectId] Onboard attempt ${attempt}/${MAX_ATTEMPTS}: not done yet, waiting...`);\n            await new Promise(resolve => setTimeout(resolve, 2000));\n\n        } catch (error) {\n            clearTimeout(timeoutId);\n            if (error.name === \"AbortError\") {\n                console.warn(`[ProjectId] onboardUser attempt ${attempt} aborted (timeout or connection removed)`);\n                if (externalSignal?.aborted) return null;   // connection gone – stop retrying\n                continue;\n            }\n            if (attempt === MAX_ATTEMPTS) {\n                console.warn(`[ProjectId] onboardUser failed after ${MAX_ATTEMPTS} attempts: ${error.message}`);\n                return null;\n            }\n            // Continue to next attempt instead of throwing (which would skip remaining retries)","sourceCodeStart":223,"sourceCodeEnd":259,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/open-sse/services/projectId.js#L223-L259","documentation":"After the onboardUser poll reports done === true, the code extracts the project ID from the response payload. If the payload completes onboarding but contains no recognizable project_id, this error is thrown. It signals an unexpected/changed Google response schema rather than an HTTP failure.","triggerScenarios":"onboardUser returns HTTP 200 with { done: true } but the response body lacks cloudaicompanionProject/projectId fields — e.g. Google changed the response shape, or the account was onboarded without a provisioned project.","commonSituations":"Upstream API schema drift after a Google-side change; account onboarded into a state with no auto-created project; a proxy or captive portal returning a manipulated 200 body.","solutions":["Log the full onboardUser response body to see what fields are actually present","Re-run loadCodeAssist after onboarding — the project may now be resolvable via the normal path instead of the onboard payload","Clear the project ID cache (or restart) so a fresh fetch is attempted, then retry","If Google changed the schema, update extractProjectIdFromOnboard in open-sse/services/projectId.js to match the new field names"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function hasProjectId(d) {\n  return Boolean(d && (d.cloudaicompanionProject?.id || d.projectId || d.project_id));\n}","tryCatchPattern":"try {\n  projectId = await fetchProjectId(accessToken, proxyOptions);\n} catch (e) {\n  if (e.message.includes('no project_id in response')) {\n    // fall back to loadCodeAssist or a configured default project id\n    projectId = await loadCodeAssistFallback(accessToken) || cfg.defaultProjectId;\n  } else throw e;\n}","preventionTips":["Log the raw onboardUser body when this fires so schema drift is visible immediately","Pin/track the Google Cloud Code API version assumptions and update extractProjectIdFromOnboard when Google changes fields","Configure a fallback/default project ID for accounts that onboard without a provisioned project","Clear the project ID cache before re-attempting so a poisoned fetch is not reused"],"tags":["schema","google-cloud","response-parsing"],"backgroundTag":"schema-validation-failed","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}