yikart/AiToEarn · error · Error

Failed to generate combined image

Error message

Failed to generate combined image

What it means

thrown by generateImageFromMessages in generateShareImages.ts when generateImageFromAllMessages resolves to a falsy blob (null/undefined) despite not throwing. The share-image pipeline (likely html-to-image rendering of chat messages) returned nothing, so the function rejects with 'Failed to generate combined image'.

Source

Thrown at project/aitoearn-web/src/components/Chat/Share/generateShareImages.ts:38

  appUrl?: string
  /** 分享链接(用于生成二维码) */
  shareUrl?: string
  /** 链接过期时间 */
  expiresAt?: string
}

export async function generateImageFromMessages(
  messages: IDisplayMessage[],
  userName?: string,
  options?: GenerateImageOptions,
): Promise<Blob[]> {
  // 禁用语言自动切换,防止 ChatMessage 中的 useTransClient 改变全局语言
  setDisableLanguageSwitch(true)

  try {
    const blob = await generateImageFromAllMessages(messages, userName, options)
    if (!blob) {
      throw new Error('Failed to generate combined image')
    }
    return [blob]
  }
  finally {
    // 恢复语言切换功能
    setDisableLanguageSwitch(false)
  }
}

async function generateImageFromAllMessages(
  messages: IDisplayMessage[],
  userName?: string,
  options?: GenerateImageOptions,
): Promise<Blob | null> {
  // 处理消息中的媒体URL
  const processedMessages = messages.map(message => ({
    ...message,
    medias:

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Inspect generateImageFromAllMessages: make it throw with a cause instead of resolving null so the failure reason isn't lost.
  2. Reduce rendered content: cap the number of messages rendered into the share image.
  3. Ensure all images in messages are same-origin or CORS-enabled (crossOrigin='anonymous') before rendering.
  4. Await document.fonts.ready and image load before invoking html-to-image.
  5. Retry once on failure; canvas rendering is intermittently flaky under memory pressure.

Example fix

// before
const blob = await generateImageFromAllMessages(messages, userName, options)
if (!blob) throw new Error('Failed to generate combined image')
// after
await document.fonts.ready
const blob = await generateImageFromAllMessages(messages.slice(-50), userName, options)
if (!blob) throw new Error('Failed to generate combined image: renderer returned null')
Defensive patterns

Strategy: fallback

Validate before calling

// sanity-check inputs before rendering
if (!messages?.length) throw new Error('没有可生成的聊天记录')

Type guard

function isBlob(v: unknown): v is Blob {
  return typeof Blob !== 'undefined' && v instanceof Blob && v.size > 0
}

Try / catch

try {
  const [blob] = await generateImageFromMessages(messages, userName)
  if (!isBlob(blob)) throw new Error('生成结果为空')
}
catch (e) {
  showToast('分享图片生成失败,请减少聊天记录后重试')
}

Prevention

When it happens

Trigger: Calling generateImageFromMessages for long conversations where the rendered DOM node is empty, has zero dimensions, contains un-renderable content (cross-origin images, unsupported CSS), or html-to-image silently fails and resolves null.

Common situations: Very long chats exceeding canvas/browser size limits; chat messages containing images from other origins tainting the canvas; fonts/emoji rendering before load; memory pressure on mobile devices aborting rendering.

Related errors


AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31). Data as JSON: /api/errors/90ce33dd4fb10f70. Report an issue: GitHub.