transloadit/uppy · error · Error

ThumbnailGenerator: The `lazy` and `waitForThumbnailsBeforeU

Error message

ThumbnailGenerator: The `lazy` and `waitForThumbnailsBeforeUpload` options are mutually exclusive. Please ensure at most one of them is set to `true`.

What it means

Constructor-time configuration error in ThumbnailGenerator: setting both lazy: true and waitForThumbnailsBeforeUpload: true is rejected because they contradict — one defers thumbnail generation until a file is visible, the other blocks upload until thumbnails are ready, which would deadlock. Thrown synchronously from the plugin constructor, i.e. at uppy.use() time.

Source

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

  thumbnailType: string

  constructor(uppy: Uppy<M, B>, opts?: ThumbnailGeneratorOptions) {
    super(uppy, { ...defaultOptions, ...opts })
    this.type = 'modifier'
    this.id = this.opts.id || 'ThumbnailGenerator'
    this.title = 'Thumbnail Generator'
    this.queue = []
    this.queueProcessing = false
    this.defaultThumbnailDimension = 200
    this.thumbnailType = this.opts.thumbnailType

    this.defaultLocale = locale

    this.i18nInit()

    if (this.opts.lazy && this.opts.waitForThumbnailsBeforeUpload) {
      throw new Error(
        'ThumbnailGenerator: The `lazy` and `waitForThumbnailsBeforeUpload` options are mutually exclusive. Please ensure at most one of them is set to `true`.',
      )
    }
  }

  createThumbnail(
    file: LocalUppyFile<M, B>,
    targetWidth: number | null,
    targetHeight: number | null,
  ): Promise<string> {
    if (file.data == null) throw new Error('File data is empty')
    const originalUrl = URL.createObjectURL(file.data)

    const onload = new Promise<HTMLImageElement>((resolve, reject) => {
      const image = new Image()
      image.src = originalUrl
      image.addEventListener('load', () => {
        URL.revokeObjectURL(originalUrl)

View on GitHub (pinned to 5d4dedd02a)

Solutions

  1. Remove one of the two options: keep lazy:true for on-demand generation, or waitForThumbnailsBeforeUpload:true to gate uploads
  2. If you want previews before upload but lazily, keep lazy:true only and rely on the dashboard's thumbnail events instead of gating upload

Example fix

// before
uppy.use(ThumbnailGenerator, {
  lazy: true,
  waitForThumbnailsBeforeUpload: true, // throws in constructor
})

// after
uppy.use(ThumbnailGenerator, { lazy: true })
Defensive patterns

Strategy: validation

Validate before calling

const opts = { lazy: true, waitForThumbnailsBeforeUpload: false }
if (opts.lazy && opts.waitForThumbnailsBeforeUpload) {
  throw new Error('Invalid thumbnail config')
}
uppy.use(ThumbnailGenerator, opts)

Type guard

null

Try / catch

try {
  uppy.use(ThumbnailGenerator, opts)
} catch (err) {
  if (/mutually exclusive/.test(err.message)) delete opts.waitForThumbnailsBeforeUpload
}

Prevention

When it happens

Trigger: new ThumbnailGenerator(uppy, { lazy: true, waitForThumbnailsBeforeUpload: true }) — the constructor immediately throws during uppy.use().

Common situations: Copy-pasting options from docs/examples that included both flags; enabling lazy loading for Dashboard performance while keeping a previously-set wait-for-upload flag from an older config.

Related errors


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