{"record":{"id":"999e81c1f99c19f1","repo":"nexu-io/open-design","slug":"field-must-be-a-non-empty-string","errorCode":null,"errorMessage":"${field} must be a non-empty string","messagePattern":"(.+?) must be a non-empty string","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"apps/daemon/src/mcp-brief.ts","lineNumber":647,"sourceCode":"  return {\n    completeCard: BRIEF_COPY[locale].completeCard,\n    confirmed: BRIEF_COPY[locale].confirmed,\n    continueWithBrief: BRIEF_COPY[locale].continueWithBrief,\n  };\n}\n\nfunction readProjectTitle(value: unknown): string {\n  if (value === undefined) return 'Untitled Open Design artifact';\n  const title = readRequiredString(value, 'projectTitle').trim();\n  if (title.length > 256) {\n    throw new Error('projectTitle must be at most 256 characters');\n  }\n  return title;\n}\n\nfunction readRequiredString(value: unknown, field: string): string {\n  if (typeof value !== 'string' || value.length === 0) {\n    throw new Error(`${field} must be a non-empty string`);\n  }\n  return value;\n}\n\nfunction readAnswerRecord(value: unknown, field: string): UnknownRecord {\n  if (value === undefined) return {};\n  if (!value || typeof value !== 'object' || Array.isArray(value)) {\n    throw new Error(`${field} must be an object`);\n  }\n  return { ...(value as UnknownRecord) };\n}\n\nfunction stableAnswerDigest(answers: OpenDesignBriefAnswers): string {\n  return JSON.stringify(\n    Object.entries(answers)\n      .sort(([left], [right]) => left.localeCompare(right))\n      .map(([key, value]) => [key, [...value]]),\n  );","sourceCodeStart":629,"sourceCodeEnd":665,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/apps/daemon/src/mcp-brief.ts#L629-L665","documentation":"readRequiredString is the generic guard used across the brief API (briefDraftId, nonce, requestId, and similar fields). It throws when a value is not a string or is empty, naming the offending field in the message.","triggerScenarios":"Omitting a required string field; passing undefined, null, or a number; passing an empty or whitespace-only string for a field that is not separately trimmed.","commonSituations":"An agent forgot to thread a field through; JSON parsed a number where a string id was expected.","solutions":["Pass a non-empty string for the named field.","If the field is optional in your flow, gate the call on its presence."],"exampleFix":"// before\nconfirm_brief({ briefDraftId: undefined, nonce, answers }) // throws [366] briefDraftId\n\n// after\nconfirm_brief({ briefDraftId: draft.briefDraftId, nonce, answers })","handlingStrategy":"validation","validationCode":"function requireStr(v: unknown, name: string): string {\n  if (typeof v !== 'string' || v.length === 0) throw new Error(`${name} must be a non-empty string`);\n  return v;\n}","typeGuard":"function isNonEmptyString(v: unknown): v is string {\n  return typeof v === 'string' && v.length > 0;\n}","tryCatchPattern":null,"preventionTips":["Validate required string fields before the call.","Thread ids straight from the producing call rather than recomputing them.","Distinguish optional vs required fields at the call site."],"tags":["mcp","brief","validation"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}