{"record":{"id":"d002d3696c302c40","repo":"CherryHQ/cherry-studio","slug":"http-response-status-errortext","errorCode":null,"errorMessage":"HTTP ${response.status}: ${errorText}","messagePattern":"HTTP (.+?): (.+?)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/ai/mcp/servers/didiMcp.ts","lineNumber":460,"sourceCode":"      method: method,\n      id: Date.now(),\n      ...(Object.keys(params).length > 0 && { params })\n    }\n\n    // API key is passed as URL parameter\n    const url = `${this.baseUrl}?key=${this.apiKey}`\n\n    const response = await fetch(url, {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json'\n      },\n      body: JSON.stringify(requestData)\n    })\n\n    if (!response.ok) {\n      const errorText = await response.text()\n      throw new Error(`HTTP ${response.status}: ${errorText}`)\n    }\n\n    const data = await response.json()\n\n    if (data.error) {\n      throw new Error(`API Error: ${JSON.stringify(data.error)}`)\n    }\n\n    return data.result\n  }\n}\n\nexport default DiDiMcpServer\n","sourceCodeStart":442,"sourceCodeEnd":474,"githubUrl":"https://github.com/CherryHQ/cherry-studio/blob/726446b54cd69ffe51a276638672f6d95ca0768c/src/main/ai/mcp/servers/didiMcp.ts#L442-L474","documentation":"Generic Error thrown by DiDiMcpServer.makeRequest when the upstream DiDi API returns a non-2xx HTTP status. The error includes the status code and the raw response body text for diagnosis. The URL embeds the API key as a query parameter, so a 401/403 typically means an invalid or expired key, while 429 indicates rate limiting and 5xx indicates an upstream outage.","triggerScenarios":"Any DiDi API call (maps_textsearch, taxi_*) that receives a non-ok HTTP response: 401/403 (bad/missing DIDI_API_KEY), 429 (rate limited), 400 (bad request params), 5xx (DiDi server error), or network-level non-ok from a proxy.","commonSituations":"DIDI_API_KEY not set, expired, or revoked; rate limit exceeded; malformed request payload; upstream DiDi gateway maintenance; network proxy returning an error page (HTML body).","solutions":["Check DIDI_API_KEY is valid and not expired (401/403).","Retry with exponential backoff for 429 and 5xx responses.","Log the full errorText to identify the upstream's specific error message.","Verify request parameters match the DiDi API schema for 400 errors."],"exampleFix":"// before\nif (!response.ok) {\n  const errorText = await response.text()\n  throw new Error(`HTTP ${response.status}: ${errorText}`)\n}\n\n// after\nif (!response.ok) {\n  const errorText = await response.text()\n  if (response.status === 429 || response.status >= 500) {\n    throw new RetryableError(`HTTP ${response.status}: ${errorText}`)\n  }\n  throw new Error(`HTTP ${response.status}: ${errorText}`)\n}","handlingStrategy":"retry","validationCode":"if (!process.env.DIDI_API_KEY) {\n  throw new Error('DIDI_API_KEY environment variable is not set')\n}","typeGuard":null,"tryCatchPattern":"async function didiRequestWithRetry(method, params, maxRetries = 3) {\n  for (let attempt = 0; attempt <= maxRetries; attempt++) {\n    try {\n      return await server.callTool(method, params)\n    } catch (e) {\n      const msg = e instanceof Error ? e.message : String(e)\n      const isRetryable = msg.includes('HTTP 429') || /HTTP 5\\d\\d/.test(msg)\n      if (!isRetryable || attempt === maxRetries) throw e\n      await new Promise(r => setTimeout(r, 2 ** attempt * 1000))\n    }\n  }\n}","preventionTips":["Ensure DIDI_API_KEY is valid and not expired before making requests.","Implement exponential backoff for 429 and 5xx responses.","Log the full errorText to diagnose upstream-specific errors.","Validate request parameters to avoid 400 errors."],"tags":["network","didi","http-error","api-key"],"backgroundTag":null,"analyzedSha":"726446b54cd69ffe51a276638672f6d95ca0768c","analyzedAt":"2026-08-12T17:30:37.448Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}