{"record":{"id":"2c566856ffe202c8","repo":"mastra-ai/mastra","slug":"skill-invocation-failed","errorCode":"skill_invocation_failed","errorMessage":"Skill invocation failed (${response.status}).","messagePattern":"Skill invocation failed \\((.+?)\\)\\.","errorType":"http","errorClass":"WorkspaceSkillInvocationError","httpStatus":null,"severity":"error","filePath":"mastracode/factory-ui/src/ui/domains/chat/services/agentControllerClient.ts","lineNumber":127,"sourceCode":"        502,\n        'invalid_response',\n      );\n    }\n    if (typeof result.skill === 'string' && typeof result.message === 'string') {\n      return { skill: result.skill, message: result.message };\n    }\n    throw new WorkspaceSkillInvocationError('Skill invocation returned an invalid response.', 502, 'invalid_response');\n  }\n\n  let error: { error?: unknown; message?: unknown } = {};\n  try {\n    error = (await response.json()) as typeof error;\n  } catch {\n    // Preserve a useful status-based fallback when an intermediary returns HTML.\n  }\n  const code = typeof error.error === 'string' ? error.error : 'skill_invocation_failed';\n  const message = typeof error.message === 'string' ? error.message : `Skill invocation failed (${response.status}).`;\n  throw new WorkspaceSkillInvocationError(message, response.status, code);\n}\n\nexport function prepareWorkspaceSkill(args: InvokeWorkspaceSkillArgs): Promise<{ skill: string; message: string }> {\n  return requestWorkspaceSkill('prepare', args);\n}\n\nexport function invokeWorkspaceSkill(args: InvokeWorkspaceSkillArgs): Promise<{ skill: string; message: string }> {\n  return requestWorkspaceSkill('invoke', args);\n}\n","sourceCodeStart":109,"sourceCodeEnd":137,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/factory-ui/src/ui/domains/chat/services/agentControllerClient.ts#L109-L137","documentation":"Fallback thrown by requestWorkspaceSkill for any non-OK HTTP status from the skill endpoint. The client first tries to read { error, message } from the JSON body; if absent (or the body is HTML from an intermediary), it uses 'Skill invocation failed (<status>).' with code skill_invocation_failed and passes the real status code through.","triggerScenarios":"Skill endpoint returns 4xx/5xx — 401/403 auth failure, 404 route missing, 500 server error during skill execution, or a gateway 502/504 whose body isn't the expected JSON error envelope.","commonSituations":"Expired session cookie hitting a protected route; skill handler throwing server-side; load balancer returning an HTML error page; API route not deployed (404).","solutions":["Check the response status in the network tab — the WorkspaceSkillInvocationError carries it as status/code.","For 401/403, re-authenticate the user session before invoking skills.","For 5xx, inspect server logs for the skill handler exception and fix or retry.","If the body was HTML, find the intermediary (proxy/LB) masking the real error and fix its configuration."],"exampleFix":"// before (client)\nconst res = await fetch(url, { method: 'POST', body });\n// after (client)\nconst res = await fetch(url, { method: 'POST', body });\nif (res.status === 401) await refreshSession(); // then retry once\nconst result = await prepareWorkspaceSkill(args);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isWorkspaceSkillError(e: unknown): e is WorkspaceSkillInvocationError {\n  return e instanceof WorkspaceSkillInvocationError;\n}","tryCatchPattern":"try {\n  const result = await invokeWorkspaceSkill(args);\n} catch (e) {\n  if (e instanceof WorkspaceSkillInvocationError) {\n    if (e.status === 401 || e.status === 403) redirectToLogin();\n    else if (e.status >= 500) scheduleRetryWithBackoff();\n    else showToast(e.message); // uses server message when present\n  }\n}","preventionTips":["Branch on e.status / e.code instead of the message string.","Re-authenticate proactively so skill calls never hit 401.","Ensure error paths return JSON { error, message } so clients see real causes.","Watch for HTML error pages from proxies/LBs masking real statuses."],"tags":["http","network","api-error","proxy"],"backgroundTag":"request-failed-status","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}