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
- 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
- Inline all external resources inside the SVG before upload (data URIs) so the canvas is not tainted
- Catch this error in requestThumbnail/on-thumbnail-error handler and skip the thumbnail gracefully
- 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
- Provide fallback previews for SVGs
- Instruct users to embed (inline) assets in SVGs
- Don't rely on thumbnails for SVG-heavy pipelines
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
- could not extract blob, probably an old browser
- ThumbnailGenerator: The `lazy` and `waitForThumbnailsBeforeU
- File data is empty
- File data is empty
AI-assisted analysis of transloadit/uppy@5d4dedd02a (2026-08-28).
Data as JSON: /api/errors/afce5dee9fe16e79.
Report an issue: GitHub.