yikart/AiToEarn · error · BadRequestException
image aspectRatio must use WIDTH:HEIGHT
Error message
image aspectRatio must use WIDTH:HEIGHT
What it means
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.
Source
Thrown at project/aitoearn-backend/apps/aitoearn-ai/src/core/draft-generation/draft-generation.service.ts:274
}
throw new AppException(ResponseCode.InvalidModel)
}
private getImageTextDraftModelConfig(model: string) {
const modelConfig = config.ai.draftGeneration.imageModels.find(m => m.model === model)
if (!modelConfig) {
throw new AppException(ResponseCode.InvalidModel)
}
return modelConfig
}
private resolveOpenAIImageSize(aspectRatio?: string, imageSize = OPENAI_IMAGE_DEFAULT_RESOLUTION): string {
const sizeProfile = getOpenAIImageSizeProfile(imageSize)
const parts = (aspectRatio ?? OPENAI_IMAGE_DEFAULT_ASPECT_RATIO).split(':')
if (parts.length !== 2) {
throw new BadRequestException('image aspectRatio must use WIDTH:HEIGHT')
}
const widthRatio = Number(parts[0])
const heightRatio = Number(parts[1])
if (!Number.isInteger(widthRatio) || !Number.isInteger(heightRatio) || widthRatio <= 0 || heightRatio <= 0) {
throw new BadRequestException('image aspectRatio must use positive integer WIDTH:HEIGHT')
}
const ratio = widthRatio / heightRatio
if (ratio < OPENAI_IMAGE_MIN_ASPECT_RATIO || ratio > OPENAI_IMAGE_MAX_ASPECT_RATIO) {
throw new BadRequestException('image aspectRatio must be between 1:3 and 3:1')
}
if (widthRatio === heightRatio) {
return sizeProfile.squareSize ?? this.resolveScaledOpenAIImageSize(widthRatio, heightRatio, sizeProfile)
}
return this.resolveScaledOpenAIImageSize(widthRatio, heightRatio, sizeProfile)View on GitHub (pinned to d3aa8bea5b)
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.
Example fix
// before body.aspectRatio = '16x9' // after body.aspectRatio = '16:9'
Defensive patterns
Strategy: validation
Validate before calling
function isValidAspectRatioFormat(v) { return typeof v === 'string' && /^[1-9]\d*:[1-9]\d*$/.test(v.trim()) }
if (aspectRatio !== undefined && !isValidAspectRatioFormat(aspectRatio)) throw new Error('aspectRatio must be WIDTH:HEIGHT, e.g. 16:9') Type guard
function isWidthHeightRatio(v: unknown): v is string {
return typeof v === 'string' && /^[1-9]\d*:[1-9]\d*$/.test(v.trim())
} Try / catch
try {
await generateDraft({ aspectRatio })
} catch (e) {
if (e.status === 400 && /aspectRatio/.test(e.message)) {
aspectRatio = '1:1' // or normalize 'x'/'-' to ':' and retry
} else throw e
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- imageSize must be one of 1K, 2K, or 4K
- image aspectRatio must use positive integer WIDTH:HEIGHT
- image aspectRatio must be between 1:3 and 3:1
- video duration is required
- OpenAI does not support multiple images
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/32da47786a7f34dd.
Report an issue: GitHub.