{"record":{"id":"797740b3fa24a738","repo":"yikart/AiToEarn","slug":"invalidmodel-797740","errorCode":"InvalidModel","errorMessage":"ResponseCode.InvalidModel","messagePattern":"ResponseCode\\.InvalidModel","errorType":"error_code","errorClass":"AppException","httpStatus":null,"severity":"error","filePath":"project/aitoearn-backend/apps/aitoearn-ai/src/core/ai/video/relay/relay-video.service.ts","lineNumber":34,"sourceCode":"  constructor(\n    private readonly relayLibService: RelayLibService,\n    private readonly aiLogRepo: AiLogRepository,\n    private readonly modelsConfigService: ModelsConfigService,\n    private readonly aiAvailability: AiAvailabilityService,\n    @Optional() private readonly relayMediaResolver?: RelayMediaResolverService,\n  ) {}\n\n  private async resolveRelayJson<T>(value: T): Promise<T> {\n    if (!this.relayMediaResolver) {\n      return value\n    }\n    return await this.relayMediaResolver.resolveJson(value)\n  }\n\n  async createFromRequest(request: UserVideoGenerationRequestDto): Promise<{ id: string }> {\n    const modelConfig = this.modelsConfigService.config.video.generation.find(m => m.name === request.model)\n    if (!modelConfig) {\n      throw new AppException(ResponseCode.InvalidModel)\n    }\n    if (request.mode && !(modelConfig.modes as readonly string[]).includes(request.mode)) {\n      throw new AppException(ResponseCode.InvalidModel)\n    }\n    const startedAt = new Date()\n\n    const payload = { ...request } as RelayVideoGenerationRequest & { userId?: string, userType?: UserType, groupId?: string }\n    delete payload.userId\n    delete payload.userType\n    delete payload.groupId\n\n    const relayPayload = await this.resolveRelayJson(payload)\n\n    const result = await this.aiAvailability.executeAsync<RelayVideoSubmitResponse>(\n      { provider: 'relay', operation: 'videoGeneration', model: request.model },\n      () => this.relayLibService.createVideo(relayPayload),\n      response => response.id || '',\n    )","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-backend/apps/aitoearn-ai/src/core/ai/video/relay/relay-video.service.ts#L16-L52","documentation":"InvalidModel is thrown by RelayVideoService.createFromRequest when request.model does not match any configured video generation model, or when the supplied mode is not in the model's allowed modes list. The Relay channel only accepts models/modes explicitly declared in modelsConfigService.config.video.generation.","triggerScenarios":"line 34: request.model is not found in modelsConfigService.config.video.generation (no entry whose name equals request.model).","commonSituations":"Typo in model name; model removed or renamed in the models config after a deployment; client using a model that only exists on OpenAI/Dashscope, not the Relay channel; stale cached model list on the client; config file/env not updated to add a newly available Relay model.","solutions":["Use a model name exactly matching an entry in the video.generation models config (check models config file/env for available names)","If the model should be supported, add it to modelsConfigService.config.video.generation and redeploy","Fetch the current model list from the API and populate client pickers from it instead of hardcoding","Confirm you are targeting the right channel: Relay-supported models differ from OpenAI/Dashscope ones"],"exampleFix":"// before\nawait relayVideoService.createFromRequest({ model: 'sora-2-pro', ... }) // not in relay config\n// after\nconst models = modelsConfigService.config.video.generation.map(m => m.name)\nawait relayVideoService.createFromRequest({ model: models.includes('sora-2-pro') ? 'sora-2-pro' : models[0], ... })","handlingStrategy":"validation","validationCode":"const names = modelsConfigService.config.video.generation.map(m => m.name)\nif (!names.includes(request.model)) {\n  throw new Error(`Unknown relay video model: ${request.model}; available: ${names.join(', ')}`)\n}","typeGuard":"function isKnownRelayVideoModel(name: string, cfg: ModelsConfig): name is string {\n  return cfg.video.generation.some(m => m.name === name)\n}","tryCatchPattern":"try {\n  await relayVideoService.createFromRequest(req)\n} catch (e) {\n  if (e instanceof AppException && e.code === ResponseCode.InvalidModel) {\n    // refresh model list from config/API and prompt user to pick a valid model\n  } else throw e\n}","preventionTips":["Populate client model pickers from the server's model list, never hardcode","Re-sync model names after backend config updates","Match exact casing/spacing of model names","Verify the model is offered on the Relay channel, not just OpenAI/Dashscope"],"tags":["invalid-model","relay","video","config"],"backgroundTag":"invalid-model","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}