{"record":{"id":"12c16cf0b6c83612","repo":"CherryHQ/cherry-studio","slug":"missing-modeldescriptor-for-dashscope-model-inp","errorCode":null,"errorMessage":"Missing modelDescriptor for DashScope model: ${input.modelId}","messagePattern":"Missing modelDescriptor for DashScope model: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/ai/provider/custom/dashscope/dashscopeTransport.ts","lineNumber":381,"sourceCode":"    default:\n      throw new Error(`Unsupported DashScope image model: ${descriptor.id}`)\n  }\n}\n\nclass DashScopeTransport implements ImageGenerationTransport {\n  private apiKey: string\n  private baseURL: string\n  private pendingDescriptors = new Map<string, DashScopeModelDescriptor>()\n\n  constructor(settings: DashScopeTransportSettings) {\n    this.apiKey = settings.apiKey\n    this.baseURL = settings.imageBaseURL || DEFAULT_DASHSCOPE_IMAGE_BASE_URL\n  }\n\n  async submit(input: ImageGenerationSubmitInput): Promise<{ taskId?: string; imageUrls?: string[] }> {\n    const descriptor = input.modelDescriptor\n    if (!descriptor) {\n      throw new Error(`Missing modelDescriptor for DashScope model: ${input.modelId}`)\n    }\n\n    const body = buildRequestBody(input, descriptor)\n    const extraHeaders: Record<string, string> = descriptor.isSync ? {} : { 'X-DashScope-Async': 'enable' }\n\n    const response = await this.request<DashScopeTaskResult>(descriptor.endpoint, 'POST', body, {\n      timeout: 120000,\n      signal: input.signal,\n      extraHeaders\n    })\n\n    if (descriptor.isSync) {\n      return { imageUrls: extractImageUrls(response.output, responseFamilyFor(descriptor)) }\n    }\n\n    const taskId = response.output.task_id\n    if (!taskId) {\n      throw new DashScopeApiError('DashScope async submit returned no task_id', 0)","sourceCodeStart":363,"sourceCodeEnd":399,"githubUrl":"https://github.com/CherryHQ/cherry-studio/blob/726446b54cd69ffe51a276638672f6d95ca0768c/src/main/ai/provider/custom/dashscope/dashscopeTransport.ts#L363-L399","documentation":"Thrown by `DashScopeTransport.submit` when `input.modelDescriptor` is undefined. The descriptor carries per-model routing (endpoint path, sync/async flag, response family) derived from the registry's `vendorTransport`; without it the transport cannot pick an endpoint or parse the response. This is a wiring invariant, not a user input.","triggerScenarios":"The painting pipeline called `submit` without injecting `modelDescriptor` into the `ImageGenerationSubmitInput`; the registry mode for the selected model lacks a `vendorTransport` entry; a code path bypassed `paintingPipeline.ts` which normally populates the descriptor.","commonSituations":"A new image mode was added to the registry without a `vendorTransport` block; a refactor stopped threading the descriptor through the job payload; a model was selected whose registry entry predates the descriptor mechanism.","solutions":["Ensure `paintingPipeline.ts` resolves and injects `modelDescriptor` from the registry's `modes[mode].vendorTransport` into the submit input.","Add a `vendorTransport` entry (endpoint, isSync) for the affected model/mode in the registry.","Guard upstream: reject model selections whose registry mode has no `vendorTransport` before reaching the transport."],"exampleFix":"// before — submit called with no descriptor\nawait transport.submit({ modelId, prompt, ... })\n// after — pipeline injects the descriptor\nawait transport.submit({ modelId, prompt, modelDescriptor: { id: modelId, endpoint, isSync }, ... })","handlingStrategy":"validation","validationCode":"if (!input.modelDescriptor) {\n  throw new Error(`No vendorTransport registered for model ${input.modelId} — check the registry's modes[mode].vendorTransport`)\n}","typeGuard":"const hasModelDescriptor = (\n  input: ImageGenerationSubmitInput\n): input is ImageGenerationSubmitInput & { modelDescriptor: ImageTransportDescriptor } =>\n  input.modelDescriptor != null","tryCatchPattern":null,"preventionTips":["Ensure paintingPipeline.ts always injects modelDescriptor before submit","Require a vendorTransport entry for every image mode in the registry","Unit-test that submit throws the descriptor error when the pipeline is bypassed"],"tags":["internal","wiring","model-descriptor","dashscope"],"backgroundTag":null,"analyzedSha":"726446b54cd69ffe51a276638672f6d95ca0768c","analyzedAt":"2026-08-12T17:30:37.448Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}