{"record":{"id":"3fc3c64d8911e02b","repo":"yikart/AiToEarn","slug":"image-aspectratio-must-be-between-1-3-and-3-1","errorCode":null,"errorMessage":"image aspectRatio must be between 1:3 and 3:1","messagePattern":"image aspectRatio must be between 1:3 and 3:1","errorType":"validation","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"project/aitoearn-backend/apps/aitoearn-ai/src/core/draft-generation/draft-generation.service.ts","lineNumber":285,"sourceCode":"    return modelConfig\n  }\n\n  private resolveOpenAIImageSize(aspectRatio?: string, imageSize = OPENAI_IMAGE_DEFAULT_RESOLUTION): string {\n    const sizeProfile = getOpenAIImageSizeProfile(imageSize)\n    const parts = (aspectRatio ?? OPENAI_IMAGE_DEFAULT_ASPECT_RATIO).split(':')\n    if (parts.length !== 2) {\n      throw new BadRequestException('image aspectRatio must use WIDTH:HEIGHT')\n    }\n\n    const widthRatio = Number(parts[0])\n    const heightRatio = Number(parts[1])\n    if (!Number.isInteger(widthRatio) || !Number.isInteger(heightRatio) || widthRatio <= 0 || heightRatio <= 0) {\n      throw new BadRequestException('image aspectRatio must use positive integer WIDTH:HEIGHT')\n    }\n\n    const ratio = widthRatio / heightRatio\n    if (ratio < OPENAI_IMAGE_MIN_ASPECT_RATIO || ratio > OPENAI_IMAGE_MAX_ASPECT_RATIO) {\n      throw new BadRequestException('image aspectRatio must be between 1:3 and 3:1')\n    }\n\n    if (widthRatio === heightRatio) {\n      return sizeProfile.squareSize ?? this.resolveScaledOpenAIImageSize(widthRatio, heightRatio, sizeProfile)\n    }\n\n    return this.resolveScaledOpenAIImageSize(widthRatio, heightRatio, sizeProfile)\n  }\n\n  private resolveScaledOpenAIImageSize(\n    widthRatio: number,\n    heightRatio: number,\n    sizeProfile: { maxEdge: number, maxPixels: number },\n  ): string {\n    const divisor = getGreatestCommonDivisor(widthRatio, heightRatio)\n    const reducedWidth = widthRatio / divisor\n    const reducedHeight = heightRatio / divisor\n    const maxScaleByEdge = Math.floor(sizeProfile.maxEdge / Math.max(reducedWidth, reducedHeight))","sourceCodeStart":267,"sourceCodeEnd":303,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-backend/apps/aitoearn-ai/src/core/draft-generation/draft-generation.service.ts#L267-L303","documentation":"Once the ratio parses to positive integers, resolveOpenAIImageSize enforces OPENAI_IMAGE_MIN_ASPECT_RATIO..OPENAI_IMAGE_MAX_ASPECT_RATIO (1/3..3). Ratios outside that band cannot map to a supported OpenAI image size and throw this BadRequestException.","triggerScenarios":"aspectRatio like '1:4' (ratio 0.25) or '4:1' (ratio 4) — extreme portrait/landscape ratios beyond 1:3 and 3:1.","commonSituations":"Generating tall banners (9:32) or wide headers (32:9) for social platforms; passing raw platform creative dimensions without clamping.","solutions":["Clamp the ratio to the supported 1:3..3:1 band before sending.","Pick the closest supported ratio, e.g. '1:3' instead of '1:4'.","Crop or letterbox the target creative concept to a supported ratio.","Compute width/height locally and cap the ratio at min(w/h, 3) or floor(max(w/h, 1/3))."],"exampleFix":"// before\naspectRatio: '1:4' // ratio 0.25 < 1/3\n// after\naspectRatio: '1:3' // ratio 0.333, supported","handlingStrategy":"validation","validationCode":"function ratioInRange(w, h) { const r = w / h; return r >= 1/3 && r <= 3 }\nconst [w, h] = aspectRatio.split(':').map(Number)\nif (!ratioInRange(w, h)) aspectRatio = clampRatio(w, h) // clamp to 1:3..3:1","typeGuard":"function isSupportedRatio(v: string): boolean {\n  const [w, h] = v.split(':').map(Number)\n  const r = w / h\n  return r >= 1 / 3 && r <= 3\n}","tryCatchPattern":"try {\n  await generateDraft({ aspectRatio })\n} catch (e) {\n  if (e.status === 400 && e.message.includes('between 1:3 and 3:1')) {\n    aspectRatio = clampToSupportedRatio(aspectRatio) // e.g. 1:4 -> 1:3\n  } else throw e\n}","preventionTips":["Clamp creative ratios to the 1:3..3:1 band before sending.","Map extreme banner/skyscraper designs to the nearest supported ratio.","Document the supported range in the UI picker.","Compute the numeric ratio and compare against 1/3 and 3 client-side."],"tags":["validation","bad-request","image-generation"],"backgroundTag":"aspect-ratio-out-of-range","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}