transloadit/uppy · error · Error

ThumbnailGenerator: The `lazy` and…

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.

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.

Appendix: 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)