{"record":{"id":"aac507c0b2695530","repo":"yikart/AiToEarn","slug":"twitter-media-id-missing","errorCode":null,"errorMessage":"Twitter media id missing","messagePattern":"Twitter media id missing","errorType":"exception","errorClass":"TwitterPlatformException","httpStatus":null,"severity":"error","filePath":"project/aitoearn-backend/apps/aitoearn-server/src/core/channels/platforms/twitter/twitter.service.ts","lineNumber":282,"sourceCode":"    const body: Media.InitializeUploadRequest = {\n      mediaType: params.mediaType,\n      totalBytes: params.totalBytes,\n    }\n    if (params.mediaCategory) {\n      body.mediaCategory = params.mediaCategory\n    }\n    const response = await this.runApiClientOperation<{ data?: TwitterMediaUploadData }>({\n      accessToken,\n      endpoint: 'POST /2/media/upload/initialize',\n      category: PlatformErrorCategory.MediaProcessingFailed,\n      call: client => client.media.initializeUpload({\n        body,\n      }),\n    })\n\n    const mediaId = response.data?.id\n    if (typeof mediaId !== 'string') {\n      throw new TwitterPlatformException('Twitter media id missing')\n    }\n    return { mediaId }\n  }\n\n  async appendMediaUpload(\n    accessToken: string,\n    params: { mediaId: string, media: Blob, segmentIndex: number },\n  ): Promise<void> {\n    const formData = new FormData()\n    formData.append('segment_index', String(params.segmentIndex))\n    formData.append('media', params.media, 'media')\n\n    try {\n      await axios.post(\n        `https://api.x.com/2/media/upload/${params.mediaId}/append`,\n        formData,\n        {\n          headers: {","sourceCodeStart":264,"sourceCodeEnd":300,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-backend/apps/aitoearn-server/src/core/channels/platforms/twitter/twitter.service.ts#L264-L300","documentation":"initMediaUpload starts a chunked media upload (INIT command) and reads response.data?.id as the media id. If the platform does not return a string id, TwitterPlatformException('Twitter media id missing') is thrown since subsequent APPEND/FINALIZE calls require it.","triggerScenarios":"INIT upload returns success without data.id, media payload exceeds platform limits causing a soft failure, malformed upload body (invalid mediaCategory/mimeType) leading to an error response the wrapper does not surface.","commonSituations":"Uploading media with an unsupported category/mime combination, exceeding size limits, Twitter API contract change or client wrapper version mismatch.","solutions":["Log the raw INIT response to inspect returned errors (e.g. 'media type not recognized')","Validate media size/type against Twitter limits (images 5MB, GIF 15MB, video 512MB) before upload","Ensure the client wrapper unwraps data consistently with the actual API version","Retry the INIT call; transient failures can produce empty responses"],"exampleFix":"// before\nconst mediaId = response.data?.id\nif (typeof mediaId !== 'string') {\n  throw new TwitterPlatformException('Twitter media id missing')\n}\n// after\nconst mediaId = response.data?.id\nif (typeof mediaId !== 'string') {\n  this.logger.error(`media INIT missing id, raw=${JSON.stringify(response)}`)\n  throw new TwitterPlatformException('Twitter media id missing')\n}","handlingStrategy":"validation","validationCode":"const validateMedia = (m: { buffer: Buffer; mime: string }) => {\n  const limits: Record<string, number> = { 'image/jpeg': 5e6, 'image/png': 5e6, 'image/gif': 15e6, 'video/mp4': 512e6 }\n  if (!limits[m.mime] || m.buffer.length > limits[m.mime]) throw new Error(`unsupported media: ${m.mime} ${m.buffer.length} bytes`)\n}","typeGuard":"function hasMediaId(r: unknown): r is { data: { id: string } } {\n  return !!r && typeof r === 'object' && typeof (r as any).data?.id === 'string'\n}","tryCatchPattern":"try {\n  const { mediaId } = await twitterService.initMediaUpload(accessToken, init)\n} catch (e) {\n  if (String(e?.message).includes('media id missing')) {\n    logger.error('INIT returned no media id', { init })\n  }\n  throw e\n}","preventionTips":["Validate media type/size before INIT","Check MIME-to-mediaCategory mapping","Pin and test the API client version","Log raw INIT responses for debugging"],"tags":["twitter","media-upload","missing-response-field","chunked-upload"],"backgroundTag":"missing-response-field","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}