{"record":{"id":"9e4d77a4285c7248","repo":"CoplayDev/unity-mcp","slug":"fal-phase-failed-status-res-status-detail-9e4d77","errorCode":null,"errorMessage":"fal {phase} failed (status={res?.Status}): {detail}","messagePattern":"fal (.+?) failed \\(status=(.+?)\\): (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"MCPForUnity/Editor/Services/AssetGen/Providers/FalAudioAdapter.cs","lineNumber":180,"sourceCode":"            }\n            catch { return \"wav\"; }\n        }\n\n        private static JObject ParseOk(HttpResult res, string apiKey, string phase)\n        {\n            string text = ProviderHttp.BodyText(res);\n\n            JObject json = null;\n            if (!string.IsNullOrEmpty(text))\n            {\n                try { json = JObject.Parse(text); } catch { /* non-JSON */ }\n            }\n\n            bool ok = res?.Ok == true;\n            if (!ok)\n            {\n                string detail = json?[\"detail\"]?.ToString() ?? json?[\"error\"]?.ToString() ?? ProviderHttp.Truncate(text);\n                throw new Exception(SecretRedactor.Scrub($\"fal {phase} failed (status={res?.Status}): {detail}\", apiKey));\n            }\n            return json ?? new JObject();\n        }\n    }\n}\n","sourceCodeStart":162,"sourceCodeEnd":186,"githubUrl":"https://github.com/CoplayDev/unity-mcp/blob/c21bf496bca87d54e75bad048563c3adb1782081/MCPForUnity/Editor/Services/AssetGen/Providers/FalAudioAdapter.cs#L162-L186","documentation":"The audio adapter's ParseOk mirrors the image one: any response with res.Ok == false throws a generic Exception with the phase, HTTP status, and a detail from the JSON 'detail'/'error' field or truncated raw text, all scrubbed of the apiKey.","triggerScenarios":"Any 4xx/5xx from fal during an audio submit/poll/download: 401/403 (auth), 422 (e.g. missing 'duration' field), 429 (rate limit), 5xx (server error).","commonSituations":"Invalid/expired API key; missing required fields like duration for a duration-controllable model; rate limiting; wrong audio model id; transient fal outage.","solutions":["Read status + detail to classify: 401/403 -> key, 422 -> body/schema (check duration), 429 -> rate limit, 5xx -> retry.","For 5xx and 429, retry with exponential backoff.","Ensure the request body includes all required fields for the chosen audio model (e.g. duration).","Verify the API key is valid with quota."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Pre-validate request inputs (e.g. duration for duration-controllable audio models).\nif (string.IsNullOrEmpty(apiKey)) throw new ArgumentException(\"apiKey required\");\nif (string.IsNullOrEmpty(modelId)) throw new ArgumentException(\"modelId required\");","typeGuard":null,"tryCatchPattern":"for (int attempt = 0; ; attempt++)\n{\n    try { return await falAudio.ParseOk(res, apiKey, phase); }\n    catch (Exception ex) when (IsTransientHttp(ex) && attempt < 4)\n    {\n        await Task.Delay((int)Math.Pow(2, attempt) * 500, ct);\n        continue;\n    }\n}","preventionTips":["For 422 on audio, check required fields such as duration per the model schema.","Retry transient statuses (429, 5xx) with backoff.","Confirm the API key is valid and has quota."],"tags":["assetgen","fal","network","api","http","audio"],"backgroundTag":null,"analyzedSha":"c21bf496bca87d54e75bad048563c3adb1782081","analyzedAt":"2026-08-13T17:36:56.095Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}