{"record":{"id":"b6514bbc3e62babf","repo":"linshenkx/prompt-optimizer","slug":"original-text-must-be-a-string","errorCode":null,"errorMessage":"Original text must be a string","messagePattern":"Original text must be a string","errorType":"validation","errorClass":"CompareValidationError","httpStatus":null,"severity":"error","filePath":"packages/core/src/services/compare/service.ts","lineNumber":66,"sourceCode":"      };\n    } catch (error) {\n      if (error instanceof CompareValidationError) {\n        throw error;\n      }\n      \n      const errorMessage = error instanceof Error ? error.message : String(error);\n      throw new CompareCalculationError(\n        `Text comparison calculation failed: ${errorMessage}`\n      );\n    }\n  }\n\n  /**\n   * 验证输入参数\n   */\n  private validateInput(original: string, optimized: string): void {\n    if (typeof original !== 'string') {\n      throw new CompareValidationError('Original text must be a string');\n    }\n    if (typeof optimized !== 'string') {\n      throw new CompareValidationError('Optimized text must be a string');\n    }\n  }\n\n  /**\n   * 执行文本对比 - 使用 jsdiff\n   */\n  private performTextComparison(\n    original: string,\n    optimized: string,\n    options: CompareOptions\n  ): TextFragment[] {\n    let diffResult: Change[];\n\n    // 根据配置处理文本预处理\n    let processedOriginal = original;","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/linshenkx/prompt-optimizer/blob/3e677b1d9f7e0493c142c175560531e7ae786dce/packages/core/src/services/compare/service.ts#L48-L84","documentation":"Thrown by buildReferencePromptPrompts when the configured reference image template's messages contain no message with role 'user'. The extractor builds its model call from a template, and a user prompt is mandatory for the request. A template with only system/assistant messages, or a mismatched role string, triggers this.","triggerScenarios":"Calling prompts / buildReferencePromptPrompts with a reference image template whose messages array has no role==='user' entry (missing, typo'd role like 'User', or empty messages).","commonSituations":"Custom user-supplied templates; template schema migration where 'user' role was renamed; template loaded from storage/JSON where the user message was dropped; localization tools altering role fields.","solutions":["Ensure the template's messages include at least one entry with role exactly 'user' containing the prompt text","Validate templates at save/import time with a schema check requiring a user-role message","Check for role casing/whitespace issues — normalize roles before collectPromptByRole"],"exampleFix":"// before\nconst template = { messages: [{ role: 'system', content: 'You extract styles.' }] }\n\n// after\nconst template = {\n  messages: [\n    { role: 'system', content: 'You extract styles.' },\n    { role: 'user', content: 'Extract the visual style from this reference image: {{image}}' },\n  ],\n}","handlingStrategy":"validation","validationCode":"function templateHasUserPrompt(template: { messages: Array<{ role: string; content?: string }> }): boolean {\n  return template.messages.some(\n    (m) => m.role?.toLowerCase() === 'user' && typeof m.content === 'string' && m.content.length > 0,\n  )\n}\nif (!templateHasUserPrompt(template)) {\n  throw new Error('Template must contain a user prompt before running extraction')\n}","typeGuard":"type ChatMessage = { role: string; content?: string }\nfunction isUserMessage(m: ChatMessage): m is ChatMessage & { role: 'user'; content: string } {\n  return m.role === 'user' && typeof m.content === 'string' && m.content.length > 0\n}","tryCatchPattern":"try {\n  const prompts = buildReferencePromptPrompts(template)\n} catch (error) {\n  if (error instanceof Error && error.message === 'Reference image template is missing a user prompt') {\n    return fixTemplateByAddingDefaultUserMessage(template)\n  }\n  throw error\n}","preventionTips":["Validate templates at import/save time, not at call time","Normalize message roles to lowercase when loading templates","Provide a default user prompt in the editor when the user clears it"],"tags":["template-validation","prompt-template","missing-user-role"],"backgroundTag":"template-schema-validation","analyzedSha":"3e677b1d9f7e0493c142c175560531e7ae786dce","analyzedAt":"2026-08-27T21:29:16.709Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}