yikart/AiToEarn · error · Error

No images were generated

Error message

No images were generated

What it means

ShareModal's image download path throws this Error when generateShareImageBlobs (invoked with appTitle/appUrl/shareUrl/expiresAt) returns an empty or null blob array, meaning no share images could be rendered. The throw is caught by the surrounding handler which shows an error to the user instead of downloading files.

Source

Thrown at project/aitoearn-web/src/components/Chat/Share/ShareModal.tsx:394

        console.error('Failed to generate share link:', err)
        toast.error('Failed to generate share link')
        return
      }
      finally {
        setGeneratingLink(false)
      }
    }

    setGeneratingImage(true)
    try {
      const blobs = await generateImageFromMessages(selectedMessages, user?.name, {
        appTitle: t('appName'),
        appUrl: t('appUrl'),
        shareUrl: link || undefined,
        expiresAt: expiresAt || undefined,
      })
      if (!blobs || blobs.length === 0)
        throw new Error('No images were generated')

      // 直接下载
      for (let i = 0; i < blobs.length; i++) {
        const blob = blobs[i]
        const a = document.createElement('a')
        const url = URL.createObjectURL(blob)
        a.href = url
        a.download
          = blobs.length === 1
            ? `aitoearn_conversation_${taskId}.png`
            : `aitoearn_${taskId}_${i + 1}.png`
        document.body.appendChild(a)
        a.click()
        a.remove()
        URL.revokeObjectURL(url)
      }
      toast.success(t('download'))
    }

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Ensure all images inside the share node are loaded (await image decode/onload) before generating blobs
  2. Serve share images via the same-origin OSS proxy (getOssProxyPath) to avoid canvas tainting
  3. Verify the share preview DOM node is mounted and has non-zero size when generating
  4. Log the generator's return value to find why blobs is empty; add a retry

Example fix

// before
const blobs = await generateShareImageBlobs({ ... })
if (!blobs || blobs.length === 0)
  throw new Error('No images were generated')
// after
const blobs = await generateShareImageBlobs({ ... })
if (!blobs || blobs.length === 0)
  throw new Error(`No images were generated (link=${link}, expiresAt=${expiresAt})`)
Defensive patterns

Strategy: validation

Validate before calling

const node = document.querySelector('[data-share-card]')
if (!node || node.clientWidth === 0) throw new Error('share node not rendered')
await Promise.all(Array.from(node.querySelectorAll('img')).map(img => img.decode?.() ?? Promise.resolve()))

Type guard

function isBlobArray(v: unknown): v is Blob[] {
  return Array.isArray(v) && v.length > 0 && v.every(b => b instanceof Blob)
}

Try / catch

try {
  const blobs = await generateShareImageBlobs({...})
  if (!isBlobArray(blobs)) throw new Error('No images were generated')
} catch (e) {
  toast.error(t('share.downloadFailed'))
}

Prevention

When it happens

Trigger: Clicking the download action in ShareModal when the canvas/html-to-image generation produced zero blobs — e.g. the share preview node was not mounted, contained cross-origin tainted images, or rendering silently failed.

Common situations: Share dialog opened before QR/preview images finished loading; cross-origin images tainting the canvas so toBlob/serialization yields nothing; browser rendering failure in headless or older browsers; shareUrl/expiry state empty.

Related errors


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