{"record":{"id":"5a6c1bc7aa671d34","repo":"yikart/AiToEarn","slug":"channelplatformmediaprocessingtimeout","errorCode":"ChannelPlatformMediaProcessingTimeout","errorMessage":"ChannelPlatformMediaProcessingTimeout","messagePattern":"ChannelPlatformMediaProcessingTimeout","errorType":"error_code","errorClass":"TwitterPlatformException","httpStatus":null,"severity":"error","filePath":"project/aitoearn-backend/apps/aitoearn-server/src/core/channels/platforms/twitter/twitter-publish.provider.ts","lineNumber":264,"sourceCode":"      }\n\n      const waitMs = (info.checkAfterSecs ?? info.check_after_secs ?? 5) * 1000\n      await new Promise(resolve => setTimeout(resolve, waitMs))\n\n      const status = await this.twitterService.getMediaStatus(accessToken, mediaId)\n      const statusInfo = status.processingInfo ?? {}\n\n      if (statusInfo.state === TwitterMediaProcessingState.Succeeded)\n        return\n      if (statusInfo.state === TwitterMediaProcessingState.Failed) {\n        throw this.mediaProcessingException('Twitter media processing failed', mediaId)\n      }\n\n      info = statusInfo\n      attempt++\n    }\n\n    throw new TwitterPlatformException({\n      code: ResponseCode.ChannelPlatformMediaProcessingTimeout,\n      category: PlatformErrorCategory.MediaProcessingFailed,\n      context: { endpoint: 'GET /2/media/upload', metadata: { mediaId } },\n      cause: {\n        type: PlatformErrorCauseType.Platform,\n        platformMessage: 'Twitter media processing timeout',\n      },\n      retryable: true,\n    })\n  }\n\n  private mediaProcessingException(message: string, mediaId: string): TwitterPlatformException {\n    return new TwitterPlatformException({\n      code: ResponseCode.ChannelPlatformMediaProcessingFailed,\n      category: PlatformErrorCategory.MediaProcessingFailed,\n      context: { endpoint: 'GET /2/media/upload', metadata: { mediaId } },\n      cause: {\n        type: PlatformErrorCauseType.Platform,","sourceCodeStart":246,"sourceCodeEnd":282,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-backend/apps/aitoearn-server/src/core/channels/platforms/twitter/twitter-publish.provider.ts#L246-L282","documentation":"Twitter media uploads go through an asynchronous processing pipeline (INIT/APPEND/FINALIZE then poll GET /2/media/upload). waitForProcessing polls the processing_info status until the media reaches a succeeded state; if the retry budget is exhausted while the media is still pending/failed, it throws TwitterPlatformException with code ChannelPlatformMediaProcessingTimeout.","triggerScenarios":"Calling uploadMedia with a large video (or many concurrent uploads) whose processing_info stays in 'pending'/'in_progress' past the polling attempt limit, or the platform returns 'failed' state that the poll loop treats as timeout.","commonSituations":"Publishing long/high-resolution videos, uploading during Twitter API latency or degraded processing, too-short polling budget configured for video assets.","solutions":["Increase the polling attempt count / interval in waitForProcessing before giving up","Verify the uploaded media conforms to Twitter media specs (size, duration, format)","Retry uploadMedia once; transient processing delays are common","Fall back to image-only or smaller video variants for the post"],"exampleFix":"// before\nfor (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) { ... }\n// after\nconst MAX_ATTEMPTS = 60 // raise budget for video uploads\nconst POLL_INTERVAL_MS = 2000\nfor (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) { ... }","handlingStrategy":"retry","validationCode":"const canUpload = (media: { size: number; type: string }) =>\n  media.size <= 512 * 1024 * 1024 && ['video/mp4', 'image/jpeg', 'image/png', 'image/gif'].includes(media.type)","typeGuard":"function isProcessingSucceeded(info?: { state?: string }): boolean {\n  return info?.state === 'succeeded'\n}","tryCatchPattern":"try {\n  await provider.uploadMedia(...)\n} catch (e) {\n  if (e?.code === 'ChannelPlatformMediaProcessingTimeout') {\n    await sleep(5000)\n    await provider.uploadMedia(...) // one retry\n  } else throw e\n}","preventionTips":["Keep videos within Twitter's recommended size/duration limits","Allow a generous polling window for video uploads","Monitor Twitter API status during large publish batches","Surface a user-visible 'media still processing, retry later' state instead of hard failure"],"tags":["twitter","media-upload","timeout","async-polling"],"backgroundTag":"media-processing-timeout","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}