{"record":{"id":"0d21e27074c6ad6a","repo":"yikart/AiToEarn","slug":"only-one-first-frame-image-is-allowed","errorCode":null,"errorMessage":"Only one first frame image is allowed","messagePattern":"Only one first frame image is allowed","errorType":"validation","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"project/aitoearn-backend/apps/aitoearn-ai/src/core/ai/video/volcengine/volcengine.service.ts","lineNumber":163,"sourceCode":"    if (content.length === 0) {\n      throw new BadRequestException('content is required')\n    }\n\n    const imageContents = content.filter((item): item is Extract<Content, { type: ContentType.ImageUrl }> => item.type === ContentType.ImageUrl)\n    const videoContents = content.filter((item): item is Extract<Content, { type: ContentType.VideoUrl }> => item.type === ContentType.VideoUrl)\n    const audioContents = content.filter((item): item is Extract<Content, { type: ContentType.AudioUrl }> => item.type === ContentType.AudioUrl)\n\n    const firstFrameImages = imageContents.filter(item => !item.role || item.role === ImageRole.FirstFrame)\n    const lastFrameImages = imageContents.filter(item => item.role === ImageRole.LastFrame)\n    const referenceImages = imageContents.filter(item => item.role === ImageRole.ReferenceImage)\n    const referenceVideos = videoContents.filter(item => item.role === VideoRole.ReferenceVideo)\n    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  }","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-backend/apps/aitoearn-ai/src/core/ai/video/volcengine/volcengine.service.ts#L145-L181","documentation":"Volcengine first-frame/last-frame (first_frame) video generation accepts at most one first frame image. validateContent counts image contents with the first-frame role and throws this BadRequestException when more than one is supplied.","triggerScenarios":"Passing 2+ content items of type ImageUrl with the first-frame role in the content array of a Volcengine generation request.","commonSituations":"Client UI letting users pick multiple start frames; bulk-upload code mapping an image list to first-frame roles; copy-paste duplicating a frame entry.","solutions":["Keep exactly one first-frame image content item","Move extra images to reference roles or remove them","Validate/deduplicate first-frame images client-side before sending"],"exampleFix":"// before\ncontent: [{ type:'image_url', role:'first_frame', url: a }, { type:'image_url', role:'first_frame', url: b }]\n// after\ncontent: [{ type:'image_url', role:'first_frame', url: a }]","handlingStrategy":"validation","validationCode":"const firstFrames = content.filter(c => c.type === 'image_url' && c.role === 'first_frame'); if (firstFrames.length > 1) throw new Error('Only one first frame image is allowed')","typeGuard":"const isSingleFirstFrame = (c: Content[]) => c.filter(i => i.type === ContentType.ImageUrl && i.role === 'first_frame').length <= 1","tryCatchPattern":"try { await generate(req) } catch (e) { if (e instanceof BadRequestException && e.message.includes('first frame')) { /* dedupe first-frame images and retry once */ } else throw e }","preventionTips":["Enforce single-select for the first-frame picker in UI","Deduplicate content items by role before sending","Keep first/last frame roles distinct from reference roles"],"tags":["validation","volcengine","content-constraints"],"backgroundTag":"too-many-items-validation","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}