anomalyco/sst · error · Error

Failed to parse JSON response: ${text}

Error message

Failed to parse JSON response: ${text}

What it means

The Vector client's invokeFunction parses the HTTP response body as JSON when status is 200/201 and content-length is non-zero. If JSON.parse fails, it throws this error embedding the raw response text. It means the vectorized function returned a 2xx response whose body is not valid JSON.

Source

Thrown at sdk/js/src/vector/index.ts:317

    const c = await client();
    const endpoint = `https://lambda.${process.env.AWS_REGION}.amazonaws.com/2015-03-31`;
    const response = await c.fetch(
      `${endpoint}/functions/${functionName}/invocations`,
      {
        method: "POST",
        headers: { Accept: "application/json" },
        body,
      }
    );

    // success
    if (response.status === 200 || response.status === 201) {
      if (response.headers.get("content-length") === "0") return undefined as T;
      const text = await response.text();
      try {
        return JSON.parse(text);
      } catch (e) {
        throw new Error(`Failed to parse JSON response: ${text}`);
      }
    }

    // error
    const error = new Error();
    const text = await response.text();
    try {
      const json = JSON.parse(text);
      error.name = json.Error?.Code;
      error.message = json.Error?.Message ?? json.message ?? text;
    } catch (e) {
      error.message = text;
    }
    error.name = error.name ?? response.headers.get("x-amzn-ErrorType");
    // @ts-expect-error
    error.requestID = response.headers.get("x-amzn-RequestId");
    // @ts-expect-error
    error.statusCode = response.status;

View on GitHub (pinned to a0bd20f762)

Solutions

  1. Check the embedded text in the error message to see what the function actually returned.
  2. Fix the vector function handler to return a JSON-serializable object (not a raw string or undefined with a non-zero body).
  3. Verify any gateway/proxy in front of the function isn't rewriting the body (e.g. HTML interstitial with 200).
  4. Confirm the response isn't being truncated (response size limits, streaming issues) — compare content-length with received bytes.
  5. Set the response Content-Type to application/json and test the endpoint directly with curl.

Example fix

// before (vector function handler)
export const handler = async () => {
  return "done"; // non-JSON body
};

// after
export const handler = async () => {
  return { status: "done" }; // JSON-serializable object
};
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check the endpoint returns JSON before relying on the client
const res = await fetch(fnUrl);
const ct = res.headers.get("content-type") ?? "";
if (!ct.includes("application/json")) throw new Error(`Vector function returns non-JSON: ${ct}`);

Type guard

function looksLikeJson(text: string): boolean {
  try { JSON.parse(text); return true; } catch { return false; }
}

Try / catch

try {
  const result = await client.invoke(payload);
} catch (e) {
  if (e instanceof Error && e.message.startsWith("Failed to parse JSON response:")) {
    console.error("Raw body was:", e.message.slice("Failed to parse JSON response:".length));
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling a vector function (via VectorClient) whose handler returns a non-JSON body (plain text, HTML, empty-ish string, truncated response) with status 200/201 and a non-zero content-length.

Common situations: The function handler returns a raw string instead of an object; a proxy/gateway returns an HTML error page with status 200; response body is truncated by a size limit or interrupted stream; content-type is text/plain.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30). Data as JSON: /api/errors/abb918227b541d4b. Report an issue: GitHub.