nexu-io/open-design · error · Error

authorized pull response must be an object

Error message

authorized pull response must be an object

What it means

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.

Source

Thrown at apps/daemon/src/collab/authorized-team-project-pull.ts:110

  record: Record<string, unknown>,
  key: string,
): string {
  const value = record[key];
  if (typeof value !== 'string' || !value.trim()) {
    throw new Error(`authorized pull receipt has invalid ${key}`);
  }
  return value;
}

function parseReceipt(stdout: string): AuthorizedTeamProjectPullReceipt {
  let parsed: unknown;
  try {
    parsed = JSON.parse(stdout.trim());
  } catch {
    throw new Error('authorized pull response is not valid JSON');
  }
  if (!isRecord(parsed)) {
    throw new Error('authorized pull response must be an object');
  }
  const version = parsed.version;
  if (!Number.isSafeInteger(version) || Number(version) < 0) {
    throw new Error('authorized pull receipt has invalid version');
  }
  return {
    schemaVersion: parsed.schemaVersion as 1,
    workspaceId: requiredString(parsed, 'workspaceId'),
    resourceTeamId: requiredString(parsed, 'resourceTeamId'),
    viewerMemberId: requiredString(parsed, 'viewerMemberId'),
    ownerMemberId: requiredString(parsed, 'ownerMemberId'),
    projectId: requiredString(parsed, 'projectId'),
    resourceId: requiredString(parsed, 'resourceId'),
    ref: parsed.ref as 'published',
    version: Number(version),
    versionId: requiredString(parsed, 'versionId'),
    manifestDigest: requiredString(parsed, 'manifestDigest'),
    lifecycleState: parsed.lifecycleState as 'active',

View on GitHub (pinned to 5be4028344)

Solutions

  1. Inspect the raw stdout to see the actual JSON shape returned.
  2. Align the Vela CLI/server version so `team-projects pull` returns a single receipt object.
  3. If the server legitimately returns a wrapper, parse and unwrap it before feeding stdout to parseReceipt.
Defensive patterns

Strategy: validation

Validate before calling

function isReceiptObject(stdout: string): boolean {
  let parsed: unknown;
  try { parsed = JSON.parse(stdout.trim()); } catch { return false; }
  return Boolean(parsed) && typeof parsed === 'object' && !Array.isArray(parsed);
}

Type guard

function isReceiptRecord(value: unknown): value is Record<string, unknown> {
  return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
}

Try / catch

try {
  parseReceipt(stdout);
} catch (err) {
  if (err instanceof Error && /must be an object/.test(err.message)) {
    // inspect shape; if a wrapper/list was returned, unwrap before re-parsing
  }
  throw err;
}

Prevention

When it happens

Trigger: Vela returned a JSON array of receipts instead of one object, a bare string status like `"ok"`, or the JSON body is `null`.

Common situations: 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.

Related errors


AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12). Data as JSON: /api/errors/321a7fd9a775cc0c. Report an issue: GitHub.