{"record":{"id":"321a7fd9a775cc0c","repo":"nexu-io/open-design","slug":"authorized-pull-response-must-be-an-object","errorCode":null,"errorMessage":"authorized pull response must be an object","messagePattern":"authorized pull response must be an object","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/daemon/src/collab/authorized-team-project-pull.ts","lineNumber":110,"sourceCode":"  record: Record<string, unknown>,\n  key: string,\n): string {\n  const value = record[key];\n  if (typeof value !== 'string' || !value.trim()) {\n    throw new Error(`authorized pull receipt has invalid ${key}`);\n  }\n  return value;\n}\n\nfunction parseReceipt(stdout: string): AuthorizedTeamProjectPullReceipt {\n  let parsed: unknown;\n  try {\n    parsed = JSON.parse(stdout.trim());\n  } catch {\n    throw new Error('authorized pull response is not valid JSON');\n  }\n  if (!isRecord(parsed)) {\n    throw new Error('authorized pull response must be an object');\n  }\n  const version = parsed.version;\n  if (!Number.isSafeInteger(version) || Number(version) < 0) {\n    throw new Error('authorized pull receipt has invalid version');\n  }\n  return {\n    schemaVersion: parsed.schemaVersion as 1,\n    workspaceId: requiredString(parsed, 'workspaceId'),\n    resourceTeamId: requiredString(parsed, 'resourceTeamId'),\n    viewerMemberId: requiredString(parsed, 'viewerMemberId'),\n    ownerMemberId: requiredString(parsed, 'ownerMemberId'),\n    projectId: requiredString(parsed, 'projectId'),\n    resourceId: requiredString(parsed, 'resourceId'),\n    ref: parsed.ref as 'published',\n    version: Number(version),\n    versionId: requiredString(parsed, 'versionId'),\n    manifestDigest: requiredString(parsed, 'manifestDigest'),\n    lifecycleState: parsed.lifecycleState as 'active',","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/apps/daemon/src/collab/authorized-team-project-pull.ts#L92-L128","documentation":"Thrown by parseReceipt after JSON.parse succeeds but the parsed value is not a plain object record — it is an array, a primitive (string/number/boolean), or null. isRecord (truthy object, not array) gates this. The receipt must be a single object, not a list or scalar.","triggerScenarios":"Vela returned a JSON array of receipts instead of one object, a bare string status like `\"ok\"`, or the JSON body is `null`.","commonSituations":"A server-side format change that wraps the receipt in a list, or a misconfigured command that returns a collection rather than a single pull receipt.","solutions":["Inspect the raw stdout to see the actual JSON shape returned.","Align the Vela CLI/server version so `team-projects pull` returns a single receipt object.","If the server legitimately returns a wrapper, parse and unwrap it before feeding stdout to parseReceipt."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"function isReceiptObject(stdout: string): boolean {\n  let parsed: unknown;\n  try { parsed = JSON.parse(stdout.trim()); } catch { return false; }\n  return Boolean(parsed) && typeof parsed === 'object' && !Array.isArray(parsed);\n}","typeGuard":"function isReceiptRecord(value: unknown): value is Record<string, unknown> {\n  return Boolean(value) && typeof value === 'object' && !Array.isArray(value);\n}","tryCatchPattern":"try {\n  parseReceipt(stdout);\n} catch (err) {\n  if (err instanceof Error && /must be an object/.test(err.message)) {\n    // inspect shape; if a wrapper/list was returned, unwrap before re-parsing\n  }\n  throw err;\n}","preventionTips":["Pin the Vela CLI/server version so `team-projects pull` returns a single receipt object.","If you introduce a wrapper envelope, unwrap it before feeding stdout to parseReceipt."],"tags":["collab","vela","receipt","json","validation","team-projects"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}