{"record":{"id":"81401f5af8e39ba0","repo":"yikart/AiToEarn","slug":"first-frame-last-frame-and-reference-media-cannot","errorCode":null,"errorMessage":"first_frame/last_frame and reference media cannot be mixed","messagePattern":"first_frame/last_frame and reference media cannot be mixed","errorType":"validation","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"project/aitoearn-backend/apps/aitoearn-ai/src/core/ai/video/volcengine/volcengine.service.ts","lineNumber":175,"sourceCode":"    const referenceAudios = audioContents.filter(item => item.role === AudioRole.ReferenceAudio)\n\n    const hasFrameScene = firstFrameImages.length > 0 || lastFrameImages.length > 0\n    const hasReferenceScene = referenceImages.length > 0 || referenceVideos.length > 0 || referenceAudios.length > 0\n\n    if (firstFrameImages.length > 1) {\n      throw new BadRequestException('Only one first frame image is allowed')\n    }\n\n    if (lastFrameImages.length > 1) {\n      throw new BadRequestException('Only one last frame image is allowed')\n    }\n\n    if (lastFrameImages.length > 0 && firstFrameImages.length === 0) {\n      throw new BadRequestException('last_frame requires first_frame')\n    }\n\n    if (hasFrameScene && hasReferenceScene) {\n      throw new BadRequestException('first_frame/last_frame and reference media cannot be mixed')\n    }\n\n    if (referenceAudios.length > 0 && referenceImages.length === 0 && referenceVideos.length === 0) {\n      throw new BadRequestException('reference_audio requires at least one reference image or reference video')\n    }\n  }\n\n  private normalizeRequest(request: UserVolcengineGenerationRequestDto) {\n    let prompt = ''\n    let inlineResolution: string | undefined\n    let inlineRatio: string | undefined\n    let inlineDuration: number | undefined\n    let inlineSeed: number | undefined\n    let inlineWatermark: boolean | undefined\n\n    const normalizedContent = request.content.map((item) => {\n      if (item.type !== ContentType.Text) {\n        return item","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-backend/apps/aitoearn-ai/src/core/ai/video/volcengine/volcengine.service.ts#L157-L193","documentation":"Volcengine generation modes are mutually exclusive: first_frame/last_frame (frame interpolation) cannot be combined with reference-based (image-to-video / reference media) generation. validateContent throws this BadRequestException when both a frame scene and a reference scene (reference image, video, or audio) are present.","triggerScenarios":"Content array containing first_frame and/or last_frame images together with any reference_image, reference_video, or reference_audio items.","commonSituations":"Clients appending all media in one array without knowing modes are exclusive; UI accumulating uploaded images across mode switches; migration code merging two requests.","solutions":["Choose one mode: either frame interpolation (first/last frame only) or reference-based generation (reference media only)","Split into two separate generation requests if both are needed","Clear frame-role items when the user switches to reference mode in the UI"],"exampleFix":"// before\ncontent: [{first_frame}, {reference_image}]\n// after\ncontent: [{type:'image_url', role:'reference_image', url: img}] // or keep only the frame pair","handlingStrategy":"validation","validationCode":"const frameRoles = ['first_frame','last_frame']; const hasFrame = content.some(c => frameRoles.includes(c.role)); const hasRef = content.some(c => ['reference_image','reference_video','reference_audio'].includes(c.role)); if (hasFrame && hasRef) throw new Error('frame and reference modes are mutually exclusive')","typeGuard":"const isExclusiveMode = (c: Content[]) => { const f = c.some(i => ['first_frame','last_frame'].includes(i.role)); const r = c.some(i => ['reference_image','reference_video','reference_audio'].includes(i.role)); return !(f && r) }","tryCatchPattern":"try { await generate(req) } catch (e) { if (e instanceof BadRequestException && e.message.includes('cannot be mixed')) { /* split into two requests: one per mode */ } else throw e }","preventionTips":["Reset frame-role selections when switching to reference mode in UI","Model the two modes as separate request types in client code","Never append all uploads into one content array blindly"],"tags":["validation","volcengine","mutually-exclusive"],"backgroundTag":"incompatible-parameters-combination","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}