{"record":{"id":"b45a7ab4cc1ac940","repo":"mastra-ai/mastra","slug":"invalid-response","errorCode":"invalid_response","errorMessage":"Skill invocation returned an invalid response.","messagePattern":"Skill invocation returned an invalid response\\.","errorType":"http","errorClass":"WorkspaceSkillInvocationError","httpStatus":502,"severity":"error","filePath":"mastracode/factory-ui/src/ui/domains/chat/services/agentControllerClient.ts","lineNumber":107,"sourceCode":"async function requestWorkspaceSkill(\n  action: 'prepare' | 'invoke',\n  { agentControllerId, resourceId, scope, name, arguments: skillArguments, baseUrl = '' }: InvokeWorkspaceSkillArgs,\n): Promise<{ skill: string; message: string }> {\n  const response = await fetch(\n    `${baseUrl}/web/agent-controller/${encodeURIComponent(agentControllerId)}/skills/${action}`,\n    {\n      method: 'POST',\n      credentials: 'include',\n      headers: { 'content-type': 'application/json' },\n      body: JSON.stringify({ resourceId, scope, name, arguments: skillArguments }),\n    },\n  );\n  if (response.ok) {\n    let result: { skill?: unknown; message?: unknown };\n    try {\n      result = (await response.json()) as typeof result;\n    } catch {\n      throw new WorkspaceSkillInvocationError(\n        'Skill invocation returned an invalid response.',\n        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';","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/factory-ui/src/ui/domains/chat/services/agentControllerClient.ts#L89-L125","documentation":"Thrown by requestWorkspaceSkill when the skill-invocation endpoint returns HTTP 200 but the body is not parseable JSON. The client expects a JSON envelope with skill and message fields; non-JSON output (e.g. an HTML error page from a proxy) fails parsing and produces this 502-coded WorkspaceSkillInvocationError.","triggerScenarios":"POST to the skill endpoint returns ok=true with a non-JSON body — e.g. an intermediary (nginx/CDN) intercepting, a dev-server proxy misroute returning HTML, or the route streaming text instead of JSON.","commonSituations":"Reverse proxy returning a cached HTML page with status 200; API route changed and now returns plain text; dev server proxy pointing at the wrong port.","solutions":["Check the network tab: inspect the 200 response body of the skill request to see what was actually returned.","Fix the proxy/intermediary returning non-JSON (or point the client at the correct API base URL).","Ensure the skill API route always responds with Content-Type: application/json, including error paths."],"exampleFix":"// before (server)\nreturn new Response('done');\n// after (server)\nreturn Response.json({ skill: skillName, message: 'done' });","handlingStrategy":"try-catch","validationCode":"const res = await fetch(url, { method: 'POST', body });\nconst ct = res.headers.get('content-type') ?? '';\nif (!ct.includes('application/json')) throw new Error('Skill endpoint returned non-JSON');","typeGuard":"function isSkillResult(v: unknown): v is { skill: string; message: string } {\n  return typeof v === 'object' && v !== null && typeof (v as any).skill === 'string' && typeof (v as any).message === 'string';\n}","tryCatchPattern":"try {\n  const { skill, message } = await prepareWorkspaceSkill(args);\n} catch (e) {\n  if (e instanceof WorkspaceSkillInvocationError && e.code === 'invalid_response') {\n    console.error('Skill endpoint returned a non-JSON 200 body — check proxy/route', e.status);\n  }\n}","preventionTips":["Assert Content-Type: application/json on all skill routes, including error paths.","Keep dev-server proxies pointed at the correct API port.","Add an integration test asserting the skill route's response shape."],"tags":["http","json-parsing","invalid-response","proxy"],"backgroundTag":"invalid-json-response","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}