CoplayDev/unity-mcp · error · Exception

OpenRouter request failed (status={res?.Status}): {detail}

Error message

OpenRouter request failed (status={res?.Status}): {detail}

What it means

Thrown by OpenRouterAdapter.ParseOk when the OpenRouter chat-completions request returns a non-ok HTTP status. The detail is read from json.error.message, then json.error, then truncated raw text, and scrubbed of the API key. OpenRouter is used for image generation via a multimodal model that returns an inline base64 image.

Source

Thrown at MCPForUnity/Editor/Services/AssetGen/Providers/OpenRouterAdapter.cs:151

            return null;
        }

        private static JObject ParseOk(HttpResult res, string apiKey)
        {
            string text = ProviderHttp.BodyText(res);

            JObject json = null;
            if (!string.IsNullOrEmpty(text))
            {
                try { json = JObject.Parse(text); } catch { /* non-JSON */ }
            }

            bool ok = res?.Ok == true;
            if (!ok)
            {
                string detail = json?["error"]?["message"]?.ToString() ?? json?["error"]?.ToString()
                                ?? ProviderHttp.Truncate(text);
                throw new Exception(SecretRedactor.Scrub($"OpenRouter request failed (status={res?.Status}): {detail}", apiKey));
            }
            return json ?? new JObject();
        }
    }
}

View on GitHub (pinned to c21bf496bc)

Solutions

  1. Read error.message from the exception text to get OpenRouter's reason.
  2. 401 -> set a valid OpenRouter API key in settings; 402 -> add credits; 429 -> back off.
  3. 400 with a modality/model complaint -> confirm the model supports image output (default google/gemini-2.5-flash-image) and leave model unset to use the default.
  4. Retry on 429/5xx with exponential backoff.
Defensive patterns

Strategy: retry

Try / catch

try { await openrouter.SubmitAsync(req, key, http, ct); }
catch (Exception ex)
{
    bool transient = ex.Message.Contains("status=429") || ex.Message.Contains("status=5");
    if (transient) await BackoffRetryAsync(() => openrouter.SubmitAsync(req, key, http, ct), ct);
}

Prevention

When it happens

Trigger: 401 invalid OpenRouter key; 400 the selected model does not support image output or the 'modalities' field; 402 insufficient credits; 429 rate limit; model name typo (e.g. a discontinued model); content-policy rejection.

Common situations: Default model google/gemini-2.5-flash-image rotated or renamed by OpenRouter; user set a text-only model for image generation; credits exhausted; a prompt flagged by safety filters.

Related errors


AI-assisted analysis of CoplayDev/unity-mcp@c21bf496bc (2026-08-13). Data as JSON: /api/errors/bf04281b53a62393. Report an issue: GitHub.