vercel/ai · error · Error

Prodia response missing multipart boundary in content-type

Error message

Prodia response missing multipart boundary in content-type: ${contentType}

What it means

The Prodia language model expects the provider API to answer image-generation jobs with a multipart response whose content-type header declares a boundary (e.g. multipart/form-data; boundary=...). The handler parses that boundary out of the header to split the body into the job JSON part and the output part. If the content-type header is absent or contains no boundary parameter, the body cannot be split, so the SDK fails fast with this error instead of producing a corrupt parse.

Solutions

  1. Verify your Prodia API key and that the request reached the correct Prodia endpoint (inspect responseHeaders captured by the SDK).
  2. Log the full content-type value from the error message to see what the server actually returned (e.g. application/json usually means an API error body).
  3. Check for proxies, gateways, or service workers between your app and Prodia that strip or rewrite the content-type header.
  4. Confirm you are on a current @ai-sdk/prodia version and the Prodia API contract still returns multipart for this model.

Example fix

// before: trusting the server response shape
const result = await model.doGenerate({ ... });

// after: pre-flight a direct call to catch non-multipart API errors early
const res = await fetch('https://api.prodia.com/v1/...', { headers: { authorization: `Bearer ${key}` } });
const ct = res.headers.get('content-type') ?? '';
if (!ct.includes('boundary=')) {
  console.error('Prodia returned non-multipart response:', await res.text());
}
Defensive patterns

Strategy: validation

Validate before calling

const ct = response.headers.get('content-type') ?? '';
if (!/^multipart\//i.test(ct) || !/boundary=/i.test(ct)) {
  throw new Error(`Expected multipart response with boundary, got: ${ct}`);
}

Type guard

function hasMultipartBoundary(contentType: string): boolean {
  return /boundary=([^\s;]+)/.test(contentType);
}

Try / catch

try {
  const result = await model.doGenerate({ ... });
} catch (error) {
  if (error instanceof Error && error.message.includes('missing multipart boundary')) {
    // inspect/log raw response content-type; likely an API error body
  }
  throw error;
}

Prevention

When it happens

Trigger: A doGenerate call on the Prodia language model where the HTTP response's content-type header is missing, is not multipart (e.g. application/json or text/html), or is multipart but lacks the boundary= parameter — typically because a proxy, gateway, or an error page intercepted the response.

Common situations: Prodia API returning a JSON error envelope with 200/4xx status instead of multipart; corporate proxies or CDNs rewriting content-type headers; hitting a wrong endpoint or an API-version mismatch; an expired/blocked API key causing the server to return an HTML error page.

Related errors


AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30). Data as JSON: /api/errors/c1e8c7b64415e2f9. Report an issue: GitHub.

Appendix: source

Thrown at packages/prodia/src/prodia-language-model.ts:377

function createLanguageMultipartResponseHandler() {
  return async ({
    response,
  }: {
    response: Response;
  }): Promise<{
    value: LanguageMultipartResult;
    responseHeaders: Record<string, string>;
  }> => {
    const contentType = response.headers.get('content-type') ?? '';
    const responseHeaders: Record<string, string> = {};
    response.headers.forEach((value, key) => {
      responseHeaders[key] = value;
    });

    const boundaryMatch = contentType.match(/boundary=([^\s;]+)/);
    if (!boundaryMatch) {
      throw new Error(
        `Prodia response missing multipart boundary in content-type: ${contentType}`,
      );
    }
    const boundary = boundaryMatch[1];

    const arrayBuffer = await response.arrayBuffer();
    const bytes = new Uint8Array(arrayBuffer);

    const parts = parseMultipart(bytes, boundary);

    let jobResult: ProdiaJobResult | undefined;
    let textContent: string | undefined;
    const fileContent: Array<{ mediaType: string; data: Uint8Array }> = [];

    for (const part of parts) {
      const contentDisposition = part.headers['content-disposition'] ?? '';
      const partContentType = part.headers['content-type'] ?? '';

View on GitHub (pinned to 69428b1f8b)