CherryHQ/cherry-studio · error · Error

HTTP ${response.status}: ${errorText}

Error message

HTTP ${response.status}: ${errorText}

What it means

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.

Source

Thrown at src/main/ai/mcp/servers/didiMcp.ts:460

      method: method,
      id: Date.now(),
      ...(Object.keys(params).length > 0 && { params })
    }

    // API key is passed as URL parameter
    const url = `${this.baseUrl}?key=${this.apiKey}`

    const response = await fetch(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(requestData)
    })

    if (!response.ok) {
      const errorText = await response.text()
      throw new Error(`HTTP ${response.status}: ${errorText}`)
    }

    const data = await response.json()

    if (data.error) {
      throw new Error(`API Error: ${JSON.stringify(data.error)}`)
    }

    return data.result
  }
}

export default DiDiMcpServer

View on GitHub (pinned to 726446b54c)

Solutions

  1. Check DIDI_API_KEY is valid and not expired (401/403).
  2. Retry with exponential backoff for 429 and 5xx responses.
  3. Log the full errorText to identify the upstream's specific error message.
  4. Verify request parameters match the DiDi API schema for 400 errors.

Example fix

// before
if (!response.ok) {
  const errorText = await response.text()
  throw new Error(`HTTP ${response.status}: ${errorText}`)
}

// after
if (!response.ok) {
  const errorText = await response.text()
  if (response.status === 429 || response.status >= 500) {
    throw new RetryableError(`HTTP ${response.status}: ${errorText}`)
  }
  throw new Error(`HTTP ${response.status}: ${errorText}`)
}
Defensive patterns

Strategy: retry

Validate before calling

if (!process.env.DIDI_API_KEY) {
  throw new Error('DIDI_API_KEY environment variable is not set')
}

Try / catch

async function didiRequestWithRetry(method, params, maxRetries = 3) {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      return await server.callTool(method, params)
    } catch (e) {
      const msg = e instanceof Error ? e.message : String(e)
      const isRetryable = msg.includes('HTTP 429') || /HTTP 5\d\d/.test(msg)
      if (!isRetryable || attempt === maxRetries) throw e
      await new Promise(r => setTimeout(r, 2 ** attempt * 1000))
    }
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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).

Related errors


AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12). Data as JSON: /api/errors/d002d3696c302c40. Report an issue: GitHub.