<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: zey-netizen</title>
    <description>The latest articles on DEV Community by zey-netizen (@zey-smith).</description>
    <link>https://dev.to/zey-smith</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4130737%2F77096f4e-2e7e-4d88-baba-236fcb13bdae.jpg</url>
      <title>DEV Community: zey-netizen</title>
      <link>https://dev.to/zey-smith</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zey-smith"/>
    <language>en</language>
    <item>
      <title>Why Your OpenAI JSON Calls Randomly Fail with "could not parse JSON body" (And How to Fix It)</title>
      <dc:creator>zey-netizen</dc:creator>
      <pubDate>Fri, 18 Sep 2026 03:28:36 +0000</pubDate>
      <link>https://dev.to/zey-smith/why-your-openai-json-calls-randomly-fail-with-could-not-parse-json-body-and-how-to-fix-it-2nip</link>
      <guid>https://dev.to/zey-smith/why-your-openai-json-calls-randomly-fail-with-could-not-parse-json-body-and-how-to-fix-it-2nip</guid>
      <description>&lt;p&gt;``You're calling OpenAI from Node.js. 99% of requests work. Then randomly:&lt;/p&gt;

&lt;p&gt;BadRequestError: 400 could not parse JSON body&lt;/p&gt;

&lt;p&gt;Or:&lt;/p&gt;

&lt;p&gt;SyntaxError: Invalid JSON: EOF while parsing an object&lt;/p&gt;

&lt;p&gt;Or, if you're using tool calling:&lt;/p&gt;

&lt;p&gt;Invalid JSON in tool call arguments&lt;/p&gt;

&lt;p&gt;You check your code. Nothing changed. You retry manually — it works. You deploy again. It breaks again.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's actually happening
&lt;/h2&gt;

&lt;p&gt;These errors are NOT your bugs. They're transient artifacts from:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Proxy / network corruption — the request body arrives at OpenAI partially mangled. OpenAI returns 400.&lt;/li&gt;
&lt;li&gt;Streaming truncation — the SDK parses JSON before the stream signals completion. Especially with max_output_tokens set low.&lt;/li&gt;
&lt;li&gt;Model-side tool call malformation — the model emits single quotes, trailing commas, or markdown code fences inside function.arguments.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every one of these is intermittent. So you can't debug it with a stack trace. You just suffer.&lt;/p&gt;

&lt;h2&gt;
  
  
  The wrong fix
&lt;/h2&gt;

&lt;p&gt;People usually do this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;try {
  const res = await client.chat.completions.create({...});
} catch (e) {
  const res = await client.chat.completions.create({...});
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You retry errors that should NOT be retried (invalid API key, rate limit that needs backoff, context length exceeded).&lt;/li&gt;
&lt;li&gt;You don't sanitize tool call args, so malformed JSON still crashes downstream.&lt;/li&gt;
&lt;li&gt;You add 20 lines of retry boilerplate per call site.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The right fix: classify then act
&lt;/h2&gt;

&lt;p&gt;Different errors need different handling:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Error&lt;/th&gt;
&lt;th&gt;Correct action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Transient 400 (could not parse JSON body)&lt;/td&gt;
&lt;td&gt;Retry with backoff + jitter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Truncated stream (EOF while parsing)&lt;/td&gt;
&lt;td&gt;Retry, possibly with higher max_tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Malformed tool args&lt;/td&gt;
&lt;td&gt;Sanitize inline, no retry needed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Invalid API key&lt;/td&gt;
&lt;td&gt;Fail fast, do NOT retry&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rate limit&lt;/td&gt;
&lt;td&gt;Retry with longer backoff&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Doing this manually is ~150 lines of code you'll write badly. Or:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @coder12-z/llm-shield

import { shield } from "@coder12-z/llm-shield";
import OpenAI from "openai";

const client = new OpenAI();

const safeCall = shield(async (prompt) =&amp;gt;
  client.chat.completions.create({
    model: "gpt-4o-mini",
    messages: [{ role: "user", content: prompt }],
    response_format: { type: "json_object" },
  }),
  {
    maxRetries: 3,
    onRetry: ({ attempt, kind }) =&amp;gt; console.log(`retry #${attempt} (${kind})`),
  }
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Three lines of config. Zero dependencies. Works with OpenAI, Anthropic, Gemini, or anything that throws Error objects with status and message.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it doesn't do
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;It doesn't repair arbitrary JSON strings — for that, use jsonrepair (&lt;a href="https://www.npmjs.com/package/jsonrepair" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/jsonrepair&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;It doesn't call LLMs for you — it wraps your existing calls.&lt;/li&gt;
&lt;li&gt;No API key. No network calls. No telemetry.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;npm: &lt;a href="https://www.npmjs.com/package/@coder12-z/llm-shield" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/@coder12-z/llm-shield&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/zey-netizen/llm-shield" rel="noopener noreferrer"&gt;https://github.com/zey-netizen/llm-shield&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Landing: &lt;a href="https://zey-netizen.github.io/llm-shield/" rel="noopener noreferrer"&gt;https://zey-netizen.github.io/llm-shield/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;MIT licensed. Feedback welcome.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>openai</category>
      <category>node</category>
      <category>llm</category>
    </item>
  </channel>
</rss>
