nexu-io/open-design · warning · Error

${field} must be an object

Error message

${field} must be an object

What it means

readAnswerRecord guards the answers argument. undefined is allowed (defaults to {}); any other non-object, null, or array is rejected. answers must be a plain record mapping question id to option id.

Source

Thrown at apps/daemon/src/mcp-brief.ts:655

  if (value === undefined) return 'Untitled Open Design artifact';
  const title = readRequiredString(value, 'projectTitle').trim();
  if (title.length > 256) {
    throw new Error('projectTitle must be at most 256 characters');
  }
  return title;
}

function readRequiredString(value: unknown, field: string): string {
  if (typeof value !== 'string' || value.length === 0) {
    throw new Error(`${field} must be a non-empty string`);
  }
  return value;
}

function readAnswerRecord(value: unknown, field: string): UnknownRecord {
  if (value === undefined) return {};
  if (!value || typeof value !== 'object' || Array.isArray(value)) {
    throw new Error(`${field} must be an object`);
  }
  return { ...(value as UnknownRecord) };
}

function stableAnswerDigest(answers: OpenDesignBriefAnswers): string {
  return JSON.stringify(
    Object.entries(answers)
      .sort(([left], [right]) => left.localeCompare(right))
      .map(([key, value]) => [key, [...value]]),
  );
}

View on GitHub (pinned to 5be4028344)

Solutions

  1. Pass answers as a plain object such as { 'website.goal': 'launch-product' }.
  2. If you stringified it, parse it first.
  3. Convert array forms to a record before calling.

Example fix

// before
confirm_brief({ briefDraftId, nonce, answers: JSON.stringify(answers) })

// after
confirm_brief({ briefDraftId, nonce, answers: { 'website.goal': 'launch-product' } })
Defensive patterns

Strategy: type-guard

Validate before calling

if (answers != null && (typeof answers !== 'object' || Array.isArray(answers))) {
  throw new Error('answers must be an object');
}

Type guard

function isAnswerRecord(v: unknown): v is Record<string, string> {
  return v == null || (typeof v === 'object' && !Array.isArray(v));
}

Prevention

When it happens

Trigger: Passing answers as a JSON string; passing an array of the form [{ id, value }]; passing null.

Common situations: The caller JSON.stringify'd answers and forgot to parse; an LLM returned an array form.

Related errors


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