{"record":{"id":"49e159153272c1f9","repo":"transloadit/uppy","slug":"call-to-thumbnail-is-not-implemented","errorCode":null,"errorMessage":"call to thumbnail is not implemented","messagePattern":"call to thumbnail is not implemented","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"packages/@uppy/companion/src/server/provider/facebook/index.ts","lineNumber":218,"sourceCode":"        }\n        const url = await getMediaUrl({ secret, token, id })\n        const stream = got.stream.get(url, { responseType: 'json' })\n        const { size } = await prepareStream(stream)\n        return { stream, size }\n      },\n    )\n  }\n\n  override async thumbnail(): Promise<{\n    stream: Readable\n    contentType: string\n  }> {\n    // not implementing this because a public thumbnail from facebook will be used instead\n    logger.error(\n      'call to thumbnail is not implemented',\n      'provider.facebook.thumbnail.error',\n    )\n    throw new Error('call to thumbnail is not implemented')\n  }\n\n  override async logout({\n    companion,\n    providerUserSession: { accessToken: token },\n  }: {\n    companion: CompanionLike\n    providerUserSession: FacebookUserSession\n  }): Promise<{ revoked: true }> {\n    return this.#withErrorHandling(\n      'provider.facebook.logout.error',\n      async () => {\n        const { secret } = (await companion.getProviderCredentials?.())!\n        if (secret == null) {\n          throw new Error('Facebook provider secret is not configured')\n        }\n\n        await runRequestBatch({","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/transloadit/uppy/blob/5d4dedd02a1ac0ae022c75c54aca76558f88e256/packages/@uppy/companion/src/server/provider/facebook/index.ts#L200-L236","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Do not call thumbnail() for Facebook — use the thumbnail link returned by list() (the image URL is public)","Branch on provider capabilities before calling thumbnail()","Catch this error and fall back to the file's public thumbnail URL"],"exampleFix":"// before\nconst { stream } = await provider.thumbnail({ id, providerUserSession })\n\n// after\nif (provider.id === 'facebook') {\n  // facebook thumbnails are public URLs returned in list results\n  return file.thumbnail\n}\nconst { stream } = await provider.thumbnail({ id, providerUserSession })","handlingStrategy":"validation","validationCode":"const THUMBNAILLESS_PROVIDERS = new Set(['facebook', 'onedrive'])\nif (!THUMBNAILLESS_PROVIDERS.has(providerId)) {\n  const { stream } = await provider.thumbnail({ id, providerUserSession })\n} else {\n  // use public thumbnail URL from list() result\n}","typeGuard":"const supportsThumbnail = (p: { id: string }): boolean =>\n  !['facebook', 'onedrive'].includes(p.id)","tryCatchPattern":"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 }","preventionTips":["Treat thumbnail() as optional per provider","Prefer public thumbnail links returned in list() results"],"tags":["facebook","thumbnail","not-implemented","companion","provider"],"backgroundTag":"method-not-implemented","analyzedSha":"5d4dedd02a1ac0ae022c75c54aca76558f88e256","analyzedAt":"2026-08-28T12:18:41.267Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}