CoplayDev/unity-mcp · error · Exception

fal {phase} failed (status={res?.Status}): {detail}

Error message

fal {phase} failed (status={res?.Status}): {detail}

What it means

ParseOk treats any HTTP response with res.Ok == false as a failure and throws a generic Exception containing the phase (submit/poll/download), the HTTP status, and a detail extracted from the JSON 'detail' or 'error' field (or the raw truncated text). The whole message is scrubbed of the apiKey.

Source

Thrown at MCPForUnity/Editor/Services/AssetGen/Providers/FalAdapter.cs:170

            string single = result["image"]?["url"]?.ToString();
            return string.IsNullOrEmpty(single) ? null : single;
        }

        private static JObject ParseOk(HttpResult res, string apiKey, string phase)
        {
            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?["detail"]?.ToString() ?? json?["error"]?.ToString() ?? ProviderHttp.Truncate(text);
                throw new Exception(SecretRedactor.Scrub($"fal {phase} failed (status={res?.Status}): {detail}", apiKey));
            }
            return json ?? new JObject();
        }
    }
}

View on GitHub (pinned to c21bf496bc)

Solutions

  1. Read status + detail in the message to classify: 401/403 -> API key, 422 -> request schema, 429 -> rate limit, 5xx -> retry.
  2. For 5xx and 429, retry with exponential backoff.
  3. Verify the API key is valid and has remaining quota.
  4. Ensure the model id and request body match fal's current schema.
Defensive patterns

Strategy: retry

Validate before calling

// Pre-validate request inputs; HTTP failure itself cannot be pre-checked.
if (string.IsNullOrEmpty(apiKey)) throw new ArgumentException("apiKey required");
if (string.IsNullOrEmpty(modelId)) throw new ArgumentException("modelId required");

Try / catch

for (int attempt = 0; ; attempt++)
{
    try { return await fal.ParseOk(res, apiKey, phase); }
    catch (Exception ex) when (IsTransientHttp(ex) && attempt < 4) // 429/5xx
    {
        await Task.Delay((int)Math.Pow(2, attempt) * 500, ct);
        continue;
    }
}

Prevention

When it happens

Trigger: Any 4xx/5xx from fal during submit, poll, or download: 401/403 (auth), 422 (malformed body), 429 (rate limit), 5xx (server error), or a transport-level non-OK result.

Common situations: Invalid or expired API key; rate limiting; wrong model id or request schema; malformed request body; transient fal outage or gateway error.

Related errors


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