transloadit/uppy · warning · Error

call to thumbnail is not implemented

Error message

call to thumbnail is not implemented

What it means

Facebook's Companion provider explicitly does not implement the thumbnail() method because Facebook serves public thumbnail URLs directly (the photo's source link is already publicly accessible). Calling thumbnail() therefore throws immediately after logging 'provider.facebook.thumbnail.error'. This is a deliberate design decision, not a bug.

Source

Thrown at packages/@uppy/companion/src/server/provider/facebook/index.ts:218

        }
        const url = await getMediaUrl({ secret, token, id })
        const stream = got.stream.get(url, { responseType: 'json' })
        const { size } = await prepareStream(stream)
        return { stream, size }
      },
    )
  }

  override async thumbnail(): Promise<{
    stream: Readable
    contentType: string
  }> {
    // not implementing this because a public thumbnail from facebook will be used instead
    logger.error(
      'call to thumbnail is not implemented',
      'provider.facebook.thumbnail.error',
    )
    throw new Error('call to thumbnail is not implemented')
  }

  override async logout({
    companion,
    providerUserSession: { accessToken: token },
  }: {
    companion: CompanionLike
    providerUserSession: FacebookUserSession
  }): Promise<{ revoked: true }> {
    return this.#withErrorHandling(
      'provider.facebook.logout.error',
      async () => {
        const { secret } = (await companion.getProviderCredentials?.())!
        if (secret == null) {
          throw new Error('Facebook provider secret is not configured')
        }

        await runRequestBatch({

View on GitHub (pinned to 5d4dedd02a)

Solutions

  1. Do not call thumbnail() for Facebook — use the thumbnail link returned by list() (the image URL is public)
  2. Branch on provider capabilities before calling thumbnail()
  3. Catch this error and fall back to the file's public thumbnail URL

Example fix

// before
const { stream } = await provider.thumbnail({ id, providerUserSession })

// after
if (provider.id === 'facebook') {
  // facebook thumbnails are public URLs returned in list results
  return file.thumbnail
}
const { stream } = await provider.thumbnail({ id, providerUserSession })
Defensive patterns

Strategy: validation

Validate before calling

const THUMBNAILLESS_PROVIDERS = new Set(['facebook', 'onedrive'])
if (!THUMBNAILLESS_PROVIDERS.has(providerId)) {
  const { stream } = await provider.thumbnail({ id, providerUserSession })
} else {
  // use public thumbnail URL from list() result
}

Type guard

const supportsThumbnail = (p: { id: string }): boolean =>
  !['facebook', 'onedrive'].includes(p.id)

Try / catch

try { await provider.thumbnail(args) } catch (e) { if (e instanceof Error && e.message === 'call to thumbnail is not implemented') { return file.thumbnail /* public URL */ } throw e }

Prevention

When it happens

Trigger: Invoking the generic provider thumbnail endpoint (GET /drive/:provider/thumbnail/:id or ProviderManager calling provider.thumbnail()) with provider set to 'facebook'. Any code path that assumes all providers implement the thumbnail interface will hit this.

Common situations: Writing generic provider code that calls thumbnail() for every provider; a UI expecting local thumbnail proxying instead of Facebook's public image URLs; tests exercising all providers' thumbnail methods.

Related errors


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