nexu-io/open-design · warning · Error

projectTitle must be at most 256 characters

Error message

projectTitle must be at most 256 characters

What it means

readProjectTitle trims the supplied projectTitle and throws if it exceeds 256 characters. Omitting projectTitle is allowed (it defaults to 'Untitled Open Design artifact'); only an over-long non-empty string fails.

Source

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

      return optionLabel ? `${questionLabel}: ${optionLabel}` : null;
    })
    .filter((line): line is string => Boolean(line));
  return lines.length > 0 ? lines.join('\n') : BRIEF_COPY[locale].noDecisions;
}

export function localMcpBriefResponseCopy(locale: LocalMcpBriefLocale) {
  return {
    completeCard: BRIEF_COPY[locale].completeCard,
    confirmed: BRIEF_COPY[locale].confirmed,
    continueWithBrief: BRIEF_COPY[locale].continueWithBrief,
  };
}

function readProjectTitle(value: unknown): string {
  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) };
}

View on GitHub (pinned to 5be4028344)

Solutions

  1. Trim the title to at most 256 characters before calling collect_brief.
  2. Pass a short label and put long text in answers, not the title.

Example fix

// before
collect_brief({ artifactType: 'website', projectTitle: longParagraph })

// after
collect_brief({ artifactType: 'website', projectTitle: longParagraph.slice(0, 256).trim() })
Defensive patterns

Strategy: validation

Validate before calling

const title = (projectTitle ?? '').toString().trim().slice(0, 256);

Prevention

When it happens

Trigger: Passing a title longer than 256 chars after trim; passing a multi-line blob; an LLM dumping a long description into projectTitle.

Common situations: User pastes a paragraph as the title; concatenating several fields into projectTitle.

Related errors


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