{"record":{"id":"32da47786a7f34dd","repo":"yikart/AiToEarn","slug":"image-aspectratio-must-use-width-height","errorCode":null,"errorMessage":"image aspectRatio must use WIDTH:HEIGHT","messagePattern":"image aspectRatio must use WIDTH:HEIGHT","errorType":"validation","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"project/aitoearn-backend/apps/aitoearn-ai/src/core/draft-generation/draft-generation.service.ts","lineNumber":274,"sourceCode":"    }\n\n    throw new AppException(ResponseCode.InvalidModel)\n  }\n\n  private getImageTextDraftModelConfig(model: string) {\n    const modelConfig = config.ai.draftGeneration.imageModels.find(m => m.model === model)\n    if (!modelConfig) {\n      throw new AppException(ResponseCode.InvalidModel)\n    }\n\n    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)","sourceCodeStart":256,"sourceCodeEnd":292,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-backend/apps/aitoearn-ai/src/core/draft-generation/draft-generation.service.ts#L256-L292","documentation":"resolveOpenAIImageSize in draft-generation.service.ts converts a user-supplied aspectRatio string into an OpenAI image size like '1024x1024'. It splits on ':', and if the split does not yield exactly 2 parts it throws this BadRequestException. The library enforces the WIDTH:HEIGHT textual format strictly before any numeric validation.","triggerScenarios":"Calling draft generation / OpenAI image resolution with aspectRatio set to values like '16-9', '16x9', '16/9', 'landscape', '1', or an empty-but-present string — anything whose split(':') does not return exactly two tokens.","commonSituations":"Clients sending UI-provided '16:9' as '16x9'; passing a preset name instead of a ratio; form input not normalized before hitting the API; the default OPENAI_IMAGE_DEFAULT_ASPECT_RATIO only applies when aspectRatio is undefined, not when it is an invalid string.","solutions":["Send aspectRatio in strict 'WIDTH:HEIGHT' form with a colon, e.g. '16:9'.","Normalize the client-side value before the call: replace '-' or 'x' with ':', or omit the field to use the default.","Sanitize whitespace: ' 16:9 ' may still split correctly but '16 : 9' will not.","Check the API docs/OpenAPI schema for the accepted aspectRatio format."],"exampleFix":"// before\nbody.aspectRatio = '16x9'\n// after\nbody.aspectRatio = '16:9'","handlingStrategy":"validation","validationCode":"function isValidAspectRatioFormat(v) { return typeof v === 'string' && /^[1-9]\\d*:[1-9]\\d*$/.test(v.trim()) }\nif (aspectRatio !== undefined && !isValidAspectRatioFormat(aspectRatio)) throw new Error('aspectRatio must be WIDTH:HEIGHT, e.g. 16:9')","typeGuard":"function isWidthHeightRatio(v: unknown): v is string {\n  return typeof v === 'string' && /^[1-9]\\d*:[1-9]\\d*$/.test(v.trim())\n}","tryCatchPattern":"try {\n  await generateDraft({ aspectRatio })\n} catch (e) {\n  if (e.status === 400 && /aspectRatio/.test(e.message)) {\n    aspectRatio = '1:1' // or normalize 'x'/'-' to ':' and retry\n  } else throw e\n}","preventionTips":["Always send ratios as colon-separated integer strings like '16:9'.","Normalize UI inputs (replace x, /, - with :) before API calls.","Omit aspectRatio entirely to accept the default.","Add client-side regex validation in the form layer."],"tags":["validation","bad-request","image-generation"],"backgroundTag":"aspect-ratio-format-invalid","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}