gitroomhq/postiz-app · error · BadBody

X failed to process the uploaded video${processing?.error?.m

Error message

X failed to process the uploaded video${processing?.error?.message ? `: ${processing.error.message}` : ''}

What it means

waitForMediaProcessing polls X's media processing status after an upload (INIT/APPEND/FINALIZE or status check); it throws when state is 'failed' or when 7 minutes elapse without 'succeeded'.

Source

Thrown at libraries/nestjs-libraries/src/integrations/social/x.provider.ts:616

      };
    }>('media/upload', { command: 'STATUS', media_id: mediaId });

    return status.data.processing_info;
  }

  // Blocking processing wait, used by the paths that still resolve everything
  // inside one activity (comments, and post() for pre-v1.0.6 workflows).
  private async waitForMediaProcessing(client: TwitterApi, mediaId: string) {
    // X drives the pace via check_after_secs; cap on accumulated wait time
    // (long videos can legitimately process for many minutes) instead of an
    // attempt count, but never poll forever.
    let waitedMs = 0;
    const maxWaitMs = 7 * 60 * 1000;
    let processing = await this.mediaProcessingStatus(client, mediaId);

    while (processing && processing.state !== 'succeeded') {
      if (processing.state === 'failed' || waitedMs >= maxWaitMs) {
        throw new BadBody(
          this.identifier,
          JSON.stringify(processing),
          Buffer.from('{}'),
          `X failed to process the uploaded video${
            processing?.error?.message ? `: ${processing.error.message}` : ''
          }`
        );
      }

      const waitMs = (processing.check_after_secs || 1) * 1000;
      await timer(waitMs);
      waitedMs += waitMs;
      processing = await this.mediaProcessingStatus(client, mediaId);
    }
  }

  // With ten X activities running concurrently (maxConcurrentJob), a user
  // publishing several posts at the same minute can 429 on the upload

View on GitHub (pinned to 0f1647f749)

Solutions

  1. Shorten/compress the video and retry
  2. Check processing_info.error in the error body for the specific X failure reason
  3. Retry the post — transient transcoder delays are common near the 7-minute cap
  4. If it consistently times out only for one file, the file itself is the problem: re-encode it
Defensive patterns

Strategy: retry

Type guard

const isTerminalOrSlow = (state?: string, waitedMs: number) => state === 'failed' || waitedMs >= 7 * 60 * 1000;

Try / catch

catch (e) { if (e instanceof BadBody && e.message.includes('process the uploaded video')) { /* safe to retry: tweet not yet created */ } throw e; }

Prevention

When it happens

Trigger: GET media/upload.json?command=STATUS keeps returning in_progress for 7 minutes, or returns state 'failed' (transcode error, too-long video, invalid media).

Common situations: Long/high-bitrate videos on busy X transcoders; rate-limited STATUS polling; media at the edge of X's limits that processes slowly then fails.

Related errors


AI-assisted analysis of gitroomhq/postiz-app@0f1647f749 (2026-08-27). Data as JSON: /api/errors/1ca3cfaca2ce4bc0. Report an issue: GitHub.