yikart/AiToEarn · warning · BadRequestException

image_tail requires a single first frame image

Error message

image_tail requires a single first frame image

What it means

BadRequestException (HTTP 400) from the Volcengine video adapter: `image_tail` (last-frame image) is only supported together with a single, scalar first-frame image (`request.image` as a single value, not an array). The legacy first-frame slot is captured in `legacyFrameImage`; if `image` is an array or absent, there is no FirstFrame to pair the LastFrame with and the request is rejected.

Source

Thrown at project/aitoearn-backend/apps/aitoearn-ai/src/core/ai/video/volcengine/volcengine.service.ts:72

    const referenceAudios = request.audios || []
    const hasExplicitReferenceMedia = additionalReferenceImages.length > 0 || referenceVideos.length > 0 || referenceAudios.length > 0
    const usesLegacyFrameInput = !!legacyFrameImage && (!hasExplicitReferenceMedia || !!request.image_tail)
    const referenceImages = [
      ...additionalReferenceImages,
      ...(!usesLegacyFrameInput && legacyFrameImage ? [legacyFrameImage] : []),
    ]

    if (usesLegacyFrameInput) {
      content.push({
        type: ContentType.ImageUrl,
        image_url: { url: await this.toAccessibleUrl(legacyFrameImage) || legacyFrameImage },
        role: ImageRole.FirstFrame,
      })
    }

    if (request.image_tail) {
      if (!legacyFrameImage) {
        throw new BadRequestException('image_tail requires a single first frame image')
      }
      content.push({
        type: ContentType.ImageUrl,
        image_url: { url: await this.toAccessibleUrl(request.image_tail) || request.image_tail },
        role: ImageRole.LastFrame,
      })
    }

    if (!request.image_tail) {
      for (const imageUrl of referenceImages) {
        content.push({
          type: ContentType.ImageUrl,
          image_url: { url: await this.toAccessibleUrl(imageUrl) || imageUrl },
          role: usesLegacyFrameInput && imageUrl === legacyFrameImage ? ImageRole.FirstFrame : ImageRole.ReferenceImage,
        })
      }
    }

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Pass the first frame as the scalar `image` field (not inside an array) whenever you set `image_tail`.
  2. Drop `image_tail` if you are using array/reference-image mode, since the combination is unsupported.
  3. Update the client UI to disable the tail-frame option when multiple reference images are selected.
  4. If the target model genuinely supports first+last with references, extend the adapter to map frames explicitly instead of relying on legacy fields.

Example fix

// before
{ prompt, image: [firstUrl, refUrl], image_tail: tailUrl } // 400
// after
{ prompt, image: firstUrl, image_tail: tailUrl }             // ok
// or, multi-reference mode:
{ prompt, image: [firstUrl, refUrl] }                        // no image_tail
Defensive patterns

Strategy: validation

Validate before calling

if (req.image_tail) {
  const singleFirstFrame = typeof req.image === 'string'
  if (!singleFirstFrame) {
    throw new Error('image_tail requires `image` to be a single URL string, not an array')
  }
}

Type guard

function canUseTailFrame(req: { image?: string | string[], images?: string[], image_tail?: string }): boolean {
  return !!req.image_tail && typeof req.image === 'string'
}

Try / catch

try {
  await videoService.userVideoGeneration(req)
} catch (e) {
  if (e instanceof BadRequestException && /image_tail/.test(e.message)) {
    // retry without image_tail, or move first frame to scalar `image`
  }
}

Prevention

When it happens

Trigger: Calling createFromRequest (via userVideoGeneration with a Volcengine-channel model) with `image_tail` set while `image` is either undefined or an array of reference images — e.g. `image: [url1, url2], image_tail: tailUrl`, or only `images: [...]` plus `image_tail`.

Common situations: Frontend refactored from single-image input to multi-image array input but kept the tail-frame toggle; clients using the new `images` reference-image field and assuming first/last frame still works; migrating from a model that supported tail frames with reference images to one that requires the strict first+last pair.

Related errors


AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31). Data as JSON: /api/errors/198da34ab47b8735. Report an issue: GitHub.