{"record":{"id":"16e626540c5463a4","repo":"vercel/ai","slug":"the-claude-code-harness-does-not-yet-support-user","errorCode":null,"errorMessage":"The claude-code harness does not yet support user message parts of type '${part.type}'. Pass a string or a user message whose content contains only text parts.","messagePattern":"The claude-code harness does not yet support user message parts of type '(.+?)'\\. Pass a string or a user message whose content contains only text parts\\.","errorType":"exception","errorClass":"HarnessCapabilityUnsupportedError","httpStatus":null,"severity":"error","filePath":"packages/harness-claude-code/src/claude-code-harness.ts","lineNumber":2098,"sourceCode":"    },\n  };\n}\n\n/*\n * Reduce a `HarnessV1Prompt` to the plain user text the bridge forwards\n * to the Claude SDK. File and image parts on the message are not yet\n * supported by the underlying runtime — throw rather than silently drop\n * them so callers learn about the gap instead of seeing mysteriously\n * truncated prompts.\n */\nfunction extractUserText(prompt: HarnessV1Prompt): string {\n  if (typeof prompt === 'string') return prompt;\n  const { content } = prompt;\n  if (typeof content === 'string') return content;\n  const parts: string[] = [];\n  for (const part of content) {\n    if (part.type !== 'text') {\n      throw new HarnessCapabilityUnsupportedError({\n        harnessId: 'claude-code',\n        message: `The claude-code harness does not yet support user message parts of type '${part.type}'. Pass a string or a user message whose content contains only text parts.`,\n      });\n    }\n    parts.push(part.text);\n  }\n  return parts.join('\\n\\n');\n}\n","sourceCodeStart":2080,"sourceCodeEnd":2107,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/harness-claude-code/src/claude-code-harness.ts#L2080-L2107","documentation":"When sending a prompt to the claude-code harness, only plain strings or user messages whose content is exclusively text parts are supported, because the harness forwards prompts to the Claude Code CLI as text commands. Any other part type (e.g. images, files, tool results) raises HarnessCapabilityUnsupportedError with this message — the harness simply lacks the capability, not just this implementation branch.","triggerScenarios":"Passing a prompt object whose `content` array contains a part with type other than 'text' (image, file, tool-call, etc.) to the session's prompt/send API; building multimodal messages for a harness that only accepts text.","commonSituations":"Reusing chat-completion-style message arrays (with image parts) across providers and feeding them to the claude-code harness; attaching screenshots or documents to a prompt; a code path generic over HarnessV1 prompts that doesn't restrict content for claude-code.","solutions":["Pass a plain string prompt instead of a structured message","Flatten the message content to text-only parts before sending; convert or drop non-text parts explicitly","Route multimodal prompts to a harness/provider that supports them, or use the claude-code harness's file/attachment options if available instead of inline parts","Add pre-send validation in your app that rejects non-text parts for this harness"],"exampleFix":"// before\nawait session.prompt({\n  role: 'user',\n  content: [\n    { type: 'text', text: 'Describe this:' },\n    { type: 'image', image: dataUrl } // unsupported\n  ]\n});\n\n// after\nawait session.prompt('Describe this:'); // string or text-only parts only","handlingStrategy":"validation","validationCode":"function assertTextOnlyPrompt(prompt) {\n  const content = typeof prompt === 'string' ? prompt : prompt.content;\n  if (typeof content === 'string') return content;\n  for (const part of content) {\n    if (part.type !== 'text') {\n      throw new Error(`Unsupported prompt part type for claude-code: ${part.type}`);\n    }\n  }\n  return content.map(p => p.text).join('\\n');\n}","typeGuard":"function isTextOnlyPrompt(prompt: unknown): prompt is string | { role: 'user'; content: string | Array<{ type: 'text'; text: string }> } {\n  if (typeof prompt === 'string') return true;\n  const p = prompt as { content?: unknown };\n  if (typeof p?.content === 'string') return true;\n  return Array.isArray(p?.content) && p.content.every((part: any) => part.type === 'text');\n}","tryCatchPattern":"try {\n  await session.prompt(message);\n} catch (err) {\n  if (err?.name === 'HarnessCapabilityUnsupportedError' && err.message.includes('user message parts of type')) {\n    // fall back to text-only extraction or a multimodal-capable harness\n  }\n  throw err;\n}","preventionTips":["Always send plain strings to the claude-code harness when possible","Validate message content is text-only before dispatching to any harness","Maintain a per-harness capability map and gate multimodal features on it","Convert images/files to supported attachment mechanisms instead of inline message parts"],"tags":["unsupported-capability","claude-code","prompt","multimodal"],"backgroundTag":"harness-capability-unsupported","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}