yikart/AiToEarn · error · AppException
InvalidModel
InvalidModel
Error message
InvalidModel
What it means
userGeminiGeneration resolves the requested Gemini image model (defaulting to 'gemini-3.1-flash-image-preview') against the configured Gemini image model registry via getGeminiImageModelConfig. If no config exists for that model name it throws AppException(ResponseCode.InvalidModel), meaning the model is unknown/not enabled in this deployment, not that the upstream call failed.
Source
Thrown at project/aitoearn-backend/apps/aitoearn-ai/src/core/ai/image/image.service.ts:249
images.push({ url: uploadResult.asset.path, data: image.imageData.toString('base64'), mimeType: image.mimeType })
}
return {
images,
usage: result.usage,
}
}
/**
* 用户 Gemini 图片生成
*/
async userGeminiGeneration(request: UserGeminiImageGenerationDto) {
const { userId, userType, model: requestedModel, ...params } = request
const model = requestedModel || 'gemini-3.1-flash-image-preview'
const modelConfig = await this.getGeminiImageModelConfig(model)
if (!modelConfig) {
throw new AppException(ResponseCode.InvalidModel)
}
const startedAt = new Date()
const result = await this.geminiGeneration(userId, { ...params, model })
const usage = result.usage || { promptTokenCount: 0, candidatesTokenCount: 0, totalTokenCount: 0 }
const duration = Date.now() - startedAt.getTime()
await this.aiLogRepo.create({
userId,
userType,
model,
channel: AiLogChannel.Gemini,
type: AiLogType.Image,
request: params,
response: { ...result, data: void 0 },
status: AiLogStatus.Success,View on GitHub (pinned to d3aa8bea5b)
Solutions
- Check the requested model against the list returned by getGeminiImageModelConfig / the configured model registry
- Correct the model name (spelling, exact id including preview suffix)
- Add the model to the Gemini image model config if it should be supported in this environment
- Omit model to fall back to the default 'gemini-3.1-flash-image-preview'
Example fix
// before
const modelConfig = await imageService.getGeminiImageModelConfig(model)
// after
if (!(await imageService.getGeminiImageModelConfig(model))) {
const available = await imageService.getGeminiImageModels()
throw new BadRequestException(`Unknown model ${model}, available: ${available.map(m => m.name).join(',')}`)
} Defensive patterns
Strategy: validation
Validate before calling
const SUPPORTED = ['gemini-3.1-flash-image-preview' /* fetch full list from model config */]
if (model && !SUPPORTED.includes(model)) throw new BadRequestException(`Unsupported Gemini image model: ${model}`) Type guard
function isValidModel(m: string | undefined): m is string {
return typeof m === 'string' && m.length > 0 // then check membership against configured list
} Try / catch
try {
await imageService.userGeminiGeneration(dto)
} catch (e) {
if (e instanceof AppException && e.code === ResponseCode.InvalidModel) {
throw new BadRequestException(`Model ${dto.model} is not available; omit 'model' to use the default`)`
}
throw e
} Prevention
- Keep the client-side model list in sync with the backend model config
- Use exact ids including preview/numeric suffixes; do not free-type model names
- Omit `model` to use the service default
- After provider model renames, update config in all environments
When it happens
Trigger: Client requests a model name that is not present in the Gemini image model config (typo, deprecated name, or a model only available in another environment), or the default model 'gemini-3.1-flash-image-preview' is not registered in the deployment's config.
Common situations: Model renamed/rotated by Google and config not updated; passing a chat model name (e.g. 'gemini-2.0-flash') to the image endpoint; staging environment missing model entries that production has.
Related errors
- ResponseCode.ConfigEditorValidationFailed
- errors.validateFailed
- No subtitle entries in response
- No response from Gemini
- Invalid subtitle data: ${z.prettifyError(result.error)}
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/18a16269cf1596c3.
Report an issue: GitHub.