yikart/AiToEarn · warning · BadRequestException
imageSize must be one of 1K, 2K, or 4K
Error message
imageSize must be one of 1K, 2K, or 4K
What it means
getOpenAIImageSizeProfile maps an imageSize tier ('1K'|'2K'|'4K') to pixel budgets used to compute OpenAI image dimensions. Any other value hits the default branch and throws a Nest BadRequestException with message 'imageSize must be one of 1K, 2K, or 4K' — a 400-class client input error, not an AppException.
Source
Thrown at project/aitoearn-backend/apps/aitoearn-ai/src/core/draft-generation/draft-generation.service.ts:94
None = 'none',
Reference = 'reference',
Edit = 'edit',
Ignored = 'ignored',
}
const OPENAI_IMAGE_DEFAULT_ASPECT_RATIO = '2:3'
const OPENAI_IMAGE_DEFAULT_RESOLUTION = '1K'
function getOpenAIImageSizeProfile(imageSize: string): { maxEdge: number, maxPixels: number, squareSize?: string } {
switch (imageSize) {
case '1K':
return { maxEdge: 1536, maxPixels: 1536 * 1024, squareSize: '1024x1024' }
case '2K':
return { maxEdge: 2560, maxPixels: 2560 * 1440 }
case '4K':
return { maxEdge: 3840, maxPixels: 3840 * 2160 }
default:
throw new BadRequestException('imageSize must be one of 1K, 2K, or 4K')
}
}
const OPENAI_IMAGE_SIZE_MULTIPLE = 16
const OPENAI_IMAGE_MIN_ASPECT_RATIO = 1 / 3
const OPENAI_IMAGE_MAX_ASPECT_RATIO = 3
function getGreatestCommonDivisor(left: number, right: number): number {
let a = Math.abs(left)
let b = Math.abs(right)
while (b !== 0) {
const next = a % b
a = b
b = next
}
return a
}View on GitHub (pinned to d3aa8bea5b)
Solutions
- Validate imageSize in the DTO with a Zod enum ['1K','2K','4K'] so invalid values are rejected with a field-level 400 before the service
- Normalize case (toUpperCase) at the boundary to tolerate '1k'
- Update callers to send only the canonical tier strings
- Map legacy size vocabulary to tiers in the controller/DTO transform
Example fix
// before
imageSize: '1k'
// after
imageSize: z.enum(['1K', '2K', '4K']).default('2K') // DTO level
// caller sends: imageSize: '1K' Defensive patterns
Strategy: validation
Validate before calling
const IMAGE_SIZES = ['1K', '2K', '4K'] as const
const normalized = typeof input.imageSize === 'string' ? input.imageSize.toUpperCase() : input.imageSize
if (!IMAGE_SIZES.includes(normalized)) {
throw new Error(`imageSize must be one of 1K, 2K, or 4K, got: ${input.imageSize}`)
} Type guard
type ImageSize = '1K' | '2K' | '4K'
function isImageSize(v: unknown): v is ImageSize {
return v === '1K' || v === '2K' || v === '4K'
} Try / catch
try {
await draftGenerationService.generateImageText({ ...dto, imageSize })
} catch (e) {
if (e instanceof BadRequestException && e.message.includes('imageSize must be one of')) {
return badRequest('imageSize must be 1K, 2K, or 4K')
}
throw e
} Prevention
- Declare imageSize with a Zod enum in the DTO so bad values fail with a field-level message
- Normalize case and legacy size vocabulary at the API boundary
- Never send raw pixel dimensions where a tier string is expected
- Share the ImageSize type between client and server to catch drift at compile time
When it happens
Trigger: A draft-generation image request supplies imageSize (or a derived size profile) with a value like '1024', '1k' (lowercase), 'HD', or undefined-coerced garbage instead of exactly '1K', '2K', or '4K'.
Common situations: Client sends lowercase '1k' or a numeric pixel size; an older API consumer uses the legacy size vocabulary ('auto', '1024x1024'); DTO lacks an enum validation so bad values reach the service.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- image aspectRatio must use WIDTH:HEIGHT
- image aspectRatio must use positive integer WIDTH:HEIGHT
- image aspectRatio must be between 1:3 and 3:1
- 参数验证失败:
- video duration is required
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/9b5ee2da5d0b1494.
Report an issue: GitHub.