{"record":{"id":"18a16269cf1596c3","repo":"yikart/AiToEarn","slug":"invalidmodel","errorCode":"InvalidModel","errorMessage":"InvalidModel","messagePattern":"InvalidModel","errorType":"error_code","errorClass":"AppException","httpStatus":400,"severity":"error","filePath":"project/aitoearn-backend/apps/aitoearn-ai/src/core/ai/image/image.service.ts","lineNumber":249,"sourceCode":"      images.push({ url: uploadResult.asset.path, data: image.imageData.toString('base64'), mimeType: image.mimeType })\n    }\n\n    return {\n      images,\n      usage: result.usage,\n    }\n  }\n\n  /**\n   * 用户 Gemini 图片生成\n   */\n  async userGeminiGeneration(request: UserGeminiImageGenerationDto) {\n    const { userId, userType, model: requestedModel, ...params } = request\n    const model = requestedModel || 'gemini-3.1-flash-image-preview'\n\n    const modelConfig = await this.getGeminiImageModelConfig(model)\n    if (!modelConfig) {\n      throw new AppException(ResponseCode.InvalidModel)\n    }\n\n    const startedAt = new Date()\n    const result = await this.geminiGeneration(userId, { ...params, model })\n\n    const usage = result.usage || { promptTokenCount: 0, candidatesTokenCount: 0, totalTokenCount: 0 }\n\n    const duration = Date.now() - startedAt.getTime()\n\n    await this.aiLogRepo.create({\n      userId,\n      userType,\n      model,\n      channel: AiLogChannel.Gemini,\n      type: AiLogType.Image,\n      request: params,\n      response: { ...result, data: void 0 },\n      status: AiLogStatus.Success,","sourceCodeStart":231,"sourceCodeEnd":267,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-backend/apps/aitoearn-ai/src/core/ai/image/image.service.ts#L231-L267","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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'"],"exampleFix":"// before\nconst modelConfig = await imageService.getGeminiImageModelConfig(model)\n// after\nif (!(await imageService.getGeminiImageModelConfig(model))) {\n  const available = await imageService.getGeminiImageModels()\n  throw new BadRequestException(`Unknown model ${model}, available: ${available.map(m => m.name).join(',')}`)\n}","handlingStrategy":"validation","validationCode":"const SUPPORTED = ['gemini-3.1-flash-image-preview' /* fetch full list from model config */]\nif (model && !SUPPORTED.includes(model)) throw new BadRequestException(`Unsupported Gemini image model: ${model}`)","typeGuard":"function isValidModel(m: string | undefined): m is string {\n  return typeof m === 'string' && m.length > 0 // then check membership against configured list\n}","tryCatchPattern":"try {\n  await imageService.userGeminiGeneration(dto)\n} catch (e) {\n  if (e instanceof AppException && e.code === ResponseCode.InvalidModel) {\n    throw new BadRequestException(`Model ${dto.model} is not available; omit 'model' to use the default`)`\n  }\n  throw e\n}","preventionTips":["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"],"tags":["model","config","validation"],"backgroundTag":"invalid-model","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}