{"record":{"id":"96341723d0dafb09","repo":"linshenkx/prompt-optimizer","slug":"text-comparison-calculation-failed-errormessage","errorCode":null,"errorMessage":"Text comparison calculation failed: ${errorMessage}","messagePattern":"Text comparison calculation failed: (.+?)","errorType":"exception","errorClass":"CompareCalculationError","httpStatus":null,"severity":"error","filePath":"packages/core/src/services/compare/service.ts","lineNumber":55,"sourceCode":"      const finalOptions = { ...DEFAULT_OPTIONS, ...options };\n      \n      // 执行对比\n      const fragments = this.performTextComparison(original, optimized, finalOptions);\n      \n      // 生成统计信息\n      const summary = this.generateSummary(fragments);\n      \n      return {\n        fragments,\n        summary\n      };\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  /**","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/linshenkx/prompt-optimizer/blob/3e677b1d9f7e0493c142c175560531e7ae786dce/packages/core/src/services/compare/service.ts#L37-L73","documentation":"Thrown when the AI model's response to a reference-image style extraction call comes back empty (blank or non-string content). The library calls a multimodal model with responseMimeType 'application/json' and requires a non-empty text body before it can normalize the result into a prompt preview. An empty body means the model refused, returned only non-text parts, or the backend stripped the content.","triggerScenarios":"Calling resolveReferencePromptPreview / the preview flow on ImageStyleExtractor with a reference image, where the model response's content is not a string or trims to empty (e.g. safety refusal, empty candidates, unsupported image input).","commonSituations":"Using a model that doesn't support image input; safety filter blocking the image; API key/quota issues returning an empty body; model returning content as an array of parts instead of a plain string; rate limiting that silently degrades responses.","solutions":["Check response.content shape — if it's an array of parts, extract text parts before trimming","Retry the call; transient empty responses from safety filters or rate limits often succeed on retry","Verify the model actually supports image (multimodal) input and the image was attached correctly","Inspect the raw model response (log it) to see whether the refusal/safety block reason is present","Fall back to a default reference prompt preview instead of failing the whole flow"],"exampleFix":"// before\nconst rawText = typeof response.content === 'string' ? response.content.trim() : ''\nif (!rawText) {\n  throw new Error('Model did not return a valid structured prompt')\n}\n\n// after (tolerate array-of-parts responses)\nconst content = response.content\nconst rawText = (typeof content === 'string'\n  ? content\n  : Array.isArray(content)\n    ? content.filter((p): p is { text: string } => typeof p?.text === 'string').map(p => p.text).join('')\n    : '').trim()\nif (!rawText) {\n  throw new Error('Model did not return a valid structured prompt')\n}","handlingStrategy":"retry","validationCode":"const content = response?.content\nconst isEmpty =\n  typeof content !== 'string' || content.trim().length === 0\nif (isEmpty) {\n  // don't call resolveReferencePromptPreview-dependent flow; retry or fallback\n  await retryWithBackoff(callModel)\n}","typeGuard":"function hasNonEmptyContent(response: unknown): response is { content: string } {\n  return (\n    typeof response === 'object' &&\n    response !== null &&\n    typeof (response as { content?: unknown }).content === 'string' &&\n    ((response as { content: string }).content.trim().length > 0)\n  )\n}","tryCatchPattern":"try {\n  const preview = await extractor.resolveReferencePromptPreview(/* ... */)\n} catch (error) {\n  if (error instanceof Error && error.message === 'Model did not return a valid structured prompt') {\n    return DEFAULT_REFERENCE_PROMPT_PREVIEW // graceful fallback\n  }\n  throw error\n}","preventionTips":["Log raw model responses in dev to spot empty/safety-blocked replies","Verify the model supports image input before enabling reference-image features","Implement one retry with backoff for transient empty responses"],"tags":["ai-model","structured-output","empty-response","image-style"],"backgroundTag":"empty-model-response","analyzedSha":"3e677b1d9f7e0493c142c175560531e7ae786dce","analyzedAt":"2026-08-27T21:29:16.709Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}