transloadit/uppy · warning · Error

cannot read image, probably an svg with external resources

Error message

cannot read image, probably an svg with external resources

What it means

canvasToBlob throws this when the modern path (canvas.toBlob) resolves with null. Per spec toBlob calls back with null when the canvas is tainted or cannot be encoded — most commonly an SVG containing external resources that taint the canvas, making thumbnail encoding impossible.

Source

Thrown at packages/@uppy/thumbnail-generator/src/index.ts:61

  type: string,
  quality: number,
): Promise<Blob | File> {
  try {
    canvas.getContext('2d')!.getImageData(0, 0, 1, 1)
  } catch (err) {
    if (err.code === 18) {
      return Promise.reject(
        new Error('cannot read image, probably an svg with external resources'),
      )
    }
  }

  if (canvas.toBlob) {
    return new Promise<Blob | null>((resolve) => {
      canvas.toBlob(resolve, type, quality)
    }).then((blob) => {
      if (blob === null) {
        throw new Error(
          'cannot read image, probably an svg with external resources',
        )
      }
      return blob
    })
  }
  return Promise.resolve()
    .then(() => {
      return dataURItoBlob(canvas.toDataURL(type, quality), {})
    })
    .then((blob) => {
      if (blob === null) {
        throw new Error('could not extract blob, probably an old browser')
      }
      return blob
    })
}

View on GitHub (pinned to 5d4dedd02a)

Solutions

  1. If SVGs don't need thumbnails, exclude them: thumbnail generator's thumbnailType or filter thumbnail generation via forEigenWaitlist — practically, restrict allowed file types or accept the failure
  2. Inline all external resources inside the SVG before upload (data URIs) so the canvas is not tainted
  3. Catch this error in requestThumbnail/on-thumbnail-error handler and skip the thumbnail gracefully
  4. Use a custom thumbnail via uppy.setFilePreview for SVG files instead of canvas rendering

Example fix

// before
// user uploads logo.svg referencing https://cdn/.../font.woff -> thumbnail throws

// after
uppy.on('thumbnail:error', (file, err) => {
  if (/svg with external resources/.test(err.message)) {
    uppy.setFilePreview(file.id, fallbackSvgIconDataUri)
  }
})
Defensive patterns

Strategy: try-catch

Validate before calling

function isSafeSvg(file: File): boolean {
  if (file.type !== 'image/svg+xml') return true
  return !/xlink:href\s*=\s*"http|href\s*=\s*"http/.test(
    awaitFirstKbOf(file),
  ) // rough check for external refs
}

Type guard

null

Try / catch

uppy.on('thumbnail:error', (file, err) => {
  if (/svg with external resources/.test(err.message)) {
    uppy.setFilePreview(file.id, genericPreviewIcon)
  }
})

Prevention

When it happens

Trigger: ThumbnailGenerator.createThumbnail processing an SVG whose markup references external images/fonts (href to remote assets). The canvas becomes tainted (or encoding fails) and toBlob(resolve) resolves null, triggering the throw inside the .then().

Common situations: Users upload SVGs with external <image href> or @import'd fonts; sites accepting image/svg+xml by mimeType; older behavior differences in canvas tainting across browsers.

Related errors


AI-assisted analysis of transloadit/uppy@5d4dedd02a (2026-08-28). Data as JSON: /api/errors/afce5dee9fe16e79. Report an issue: GitHub.