{"record":{"id":"02e51631b7ecac32","repo":"can1357/oh-my-pi","slug":"failed-to-unmarshal-onboarduser-operation-resul","errorCode":null,"errorMessage":"failed to unmarshal OnboardUser operation: ${result.summary}","messagePattern":"failed to unmarshal OnboardUser operation: (.+?)","errorType":"exception","errorClass":"AIError.OAuthError","httpStatus":null,"severity":"error","filePath":"packages/ai/src/registry/oauth/google-antigravity.ts","lineNumber":108,"sourceCode":"\t\"response?\": onboardUserResponseSchema.or(\"null\"),\n});\ntype OnboardOperation = typeof onboardOperationSchema.infer;\n\nfunction parseLoadCodeAssistResponse(payload: unknown): LoadCodeAssistResponse {\n\tconst result = loadCodeAssistResponseSchema(payload);\n\tif (result instanceof type.errors) {\n\t\tthrow new AIError.OAuthError(`failed to unmarshal LoadCodeAssistResponse: ${result.summary}`, {\n\t\t\tkind: \"provisioning\",\n\t\t\tprovider: PROVIDER,\n\t\t});\n\t}\n\treturn result;\n}\n\nfunction parseOnboardOperation(payload: unknown): OnboardOperation {\n\tconst result = onboardOperationSchema(payload);\n\tif (result instanceof type.errors) {\n\t\tthrow new AIError.OAuthError(`failed to unmarshal OnboardUser operation: ${result.summary}`, {\n\t\t\tkind: \"provisioning\",\n\t\t\tprovider: PROVIDER,\n\t\t});\n\t}\n\treturn result;\n}\n\nfunction extractProjectId(payload: LoadCodeAssistResponse): string | undefined {\n\tconst projectId = payload.cloudaicompanionProject;\n\treturn projectId && projectId.length > 0 ? projectId : undefined;\n}\n\nfunction hasMessageField(payload: LoadCodeAssistResponse, field: \"currentTier\" | \"paidTier\"): boolean {\n\treturn payload[field] !== undefined && payload[field] !== null;\n}\n\nfunction isFreeTierAllowed(payload: LoadCodeAssistResponse): boolean {\n\treturn payload.allowedTiers?.some(tier => tier.id === FREE_TIER_ID) === true;","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/ai/src/registry/oauth/google-antigravity.ts#L90-L126","documentation":"parseOnboardOperation validates responses from Cloud Code Assist's onboardUser endpoint and its long-running operation polling (GET v1internal/{name}) against onboardOperationSchema (name, done, error, response with @type). A non-conforming payload throws this provisioning OAuthError with the schema summary. The Antigravity onboarding state machine cannot proceed on a malformed operation object.","triggerScenarios":"onboardUser or the operation-poll GET returns 200 JSON failing onboardOperationSchema — e.g. missing '@type' on the response sub-object, error/response fields of the wrong type, or Google altering the operation envelope; also occurs on every poll iteration until the operation completes.","commonSituations":"Google-side API shape drift on the v1internal operations endpoint; intermediate proxy mangling the payload; project provisioning stuck so repeated polls hit an unexpected payload; outdated library version predating a schema change.","solutions":["Inspect result.summary in the message to identify the mismatched field (most commonly the response '@type').","Update to the latest library version in case the operation schema needs adjusting for a Google change.","Retry onboarding later — if provisioning is stuck server-side, the poll loop may surface transient malformed payloads.","Capture and log the raw operation JSON to compare with the schema and file/report the drift.","Verify the account has Cloud Code Assist access; restricted accounts can receive alternate payloads."],"exampleFix":"// before: blind cast of the operation\nconst op = (await res.json()) as OnboardOperation;\n\n// after: validate and surface the summary\nconst result = onboardOperationSchema(await res.json());\nif (result instanceof type.errors) {\n  throw new Error(`onboardUser operation malformed: ${result.summary}`);\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function looksLikeOperation(p: unknown): boolean {\n  if (typeof p !== \"object\" || p === null) return false;\n  const o = p as Record<string, unknown>;\n  return \"done\" in o || \"name\" in o || \"@type\" in o;\n}","tryCatchPattern":"try {\n  await onboardUser(context);\n} catch (err) {\n  if (err instanceof AIError.OAuthError && String(err.message).startsWith(\"failed to unmarshal OnboardUser operation\")) {\n    logger.error(\"onboardUser payload schema mismatch\", { summary: String(err.message) });\n    // surface to user; likely needs a library update for a Google API change\n  } else {\n    throw err;\n  }\n}","preventionTips":["Pin/update the library version deliberately — the operation schema must track Google's endpoint.","Don't hammer the polling endpoint; a 30s onboarding deadline with 1s polls is built in.","Capture raw operation JSON on failure for upstream bug reports.","Check that the account is fully provisioned for Cloud Code Assist before running login."],"tags":["google","oauth","schema-validation","provisioning","long-running-operation"],"backgroundTag":"schema-validation-failed","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}