JSON Missing Bracket Error: How to Find and Fix It
Missing brackets and braces are the second most common JSON syntax error from LLM output. Learn how to find the exact location, understand why it happens in AI pipelines, and fix it automatically.
Have broken JSON right now? Fix it free in under 1 second — no signup.
Fix My JSON →A JSON missing bracket error means your JSON has an unclosed array [ or object { — or the closing ] or } is in the wrong place. The parser reaches the end of the string expecting a closing delimiter that never arrives, or finds a closing ] where it expected }.
These errors are the second most common JSON failure in LLM pipelines after trailing commas. They're also the hardest to fix manually when they occur in deeply nested structures — because the error message points to the end of the file, not the location of the missing bracket.
The Error Messages
Python (json.loads):
json.decoder.JSONDecodeError: Unterminated string starting at: line 1 column 847 (char 846)
or
json.decoder.JSONDecodeError: Expecting ',' delimiter: line 8 column 1 (char 201)
or
json.decoder.JSONDecodeError: Extra data: line 1 column 203 (char 202)
Node.js (JSON.parse):
SyntaxError: Unexpected end of JSON input
or
SyntaxError: Expected ',' or '}' after property value in JSON at position 201
Go (encoding/json):
unexpected end of JSON input
The most misleading error is Unexpected end of JSON input — it means the parser hit the end of the string before all open brackets were closed. The bracket is missing, but the error message gives you no location to start looking.
Why Missing Brackets Happen in 2026
Cause 1: LLM Token Limit Truncation (Most Common)
The most common cause in 2026 is LLM output that was cut off when the model hit its max_tokens limit mid-response. If a model is generating a deeply nested JSON structure and runs out of output budget, it stops — leaving all the unclosed brackets from the current nesting level open.
{
"users": [
{
"name": "Alice",
"metadata": {
"scores": [92, 88, 95
The model stopped here. The unclosed brackets are: [ (scores array), { (metadata object), { (Alice's object), [ (users array) — four missing closing delimiters.
This pattern is almost impossible to fix manually when the nesting depth is unknown. A repair tool reconstructs the structure by tracking the bracket stack.
Cause 2: Manual Copy-Paste Errors
Copying JSON from an API response, a log file, or a code editor and accidentally truncating the end is the original cause of this error. The JSON appears complete visually (the value data looks right) but the last few characters were cut off.
Cause 3: Stream Buffer Truncation
When consuming JSON from a streaming API (Server-Sent Events, WebSockets, HTTP chunked transfer), if the stream closes unexpectedly or the buffer overflows, you receive partial JSON. The data you have is valid up to the truncation point — but the JSON structure is open.
Cause 4: Mismatched Bracket Types
A less common but harder-to-spot error: using } where ] was expected, or vice versa:
{
"tags": ["senior", "backend"
}
}
The array tags was opened with [ but closed with }. The parser expects ] to close the array, finds } instead, and throws an error. This is common when a model has lost track of the current bracket context mid-generation.
How to Find the Missing Bracket
Method 1: Auto-Repair (Fastest)
Paste your JSON into aijsonmedic.com. The repair engine maintains a bracket stack as it parses — it knows exactly which brackets are open and what closing delimiters are needed. On truncated LLM output, it adds all missing closers in the correct order.
Method 2: Bracket Balance Counter
For JSON you want to inspect manually before fixing:
def find_bracket_imbalance(json_str: str) -> dict:
"""Count unmatched brackets."""
in_string = False
escape_next = False
stack = []
pairs = {'}': '{', ']': '['}
for i, char in enumerate(json_str):
if escape_next:
escape_next = False
continue
if char == '\\' and in_string:
escape_next = True
continue
if char == '"':
in_string = not in_string
continue
if in_string:
continue
if char in '{[':
stack.append((char, i))
elif char in '}]':
if stack and stack[-1][0] == pairs[char]:
stack.pop()
else:
return {"error": f"Mismatched {char} at position {i}", "stack": stack}
return {
"unclosed": [{"bracket": b, "position": p} for b, p in stack],
"balanced": len(stack) == 0
}
broken = '{"users": [{"name": "Alice", "tags": ["senior"'
result = find_bracket_imbalance(broken)
print(result)
# {'unclosed': [('{', 0), ('[', 10), ('{', 11), ('[', 31)], 'balanced': False}
This tells you which brackets are open and where they started — giving you the information to manually add the missing closers.
Method 3: VS Code Bracket Matching
Open your JSON in VS Code, click on any opening bracket, and VS Code highlights its matching closing bracket (or shows no match if it's unclosed). Walk through the structure from the outermost to innermost bracket to find the unclosed one.
Method 4: Command-Line jq
echo '{"name": "Alice", "tags": ["senior"' | jq .
# parse error (Unexpected end of file) at EOF at line 1, column 37
jq gives you the exact character position of the parse failure — which is the point where the missing bracket was expected.
How to Fix Missing Brackets
Option 1: Fix Online (Recommended)
aijsonmedic.com — handles bracket imbalance at any nesting depth. The repair engine reconstructs the complete closing sequence (e.g.,]}]} for a deeply nested truncation).
Option 2: Python — json_repair Library
from json_repair import repair_json
import json
# Truncated LLM output — 4 unclosed brackets
broken = '''
{
"users": [
{
"name": "Alice",
"tags": ["senior", "backend"
'''
fixed_str = repair_json(broken)
data = json.loads(fixed_str)
print(data)
# {'users': [{'name': 'Alice', 'tags': ['senior', 'backend']}]}
The library adds all missing closing delimiters and returns valid JSON.
Option 3: JavaScript — jsonrepair Library
import { jsonrepair } from "jsonrepair";
const broken = `{
"users": [
{
"name": "Alice",
"tags": ["senior", "backend"
`;
const fixed = jsonrepair(broken);
const data = JSON.parse(fixed);
console.log(data);
// { users: [{ name: 'Alice', tags: ['senior', 'backend'] }] }
Option 4: Fix Manually (Simple Cases)
For shallow nesting (1–2 levels), you can manually count open vs. closed brackets:
Open: { [ { [
Close: }
Missing: ] } ]
If your JSON has { at position 0, [ at position 10, { at position 15, [ at position 30, and only one } at position 200, you need to add ]}]} at the end (closing in reverse open order: innermost first).
This gets impractical fast. For anything beyond 2 nesting levels, use an automated repair tool.
Preventing Missing Brackets in LLM Pipelines
Increase max_tokens
The most common cause is a truncated model response. Increase your max_tokens budget to ensure the model has room to close all open structures:
# Before: model runs out of budget mid-JSON
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=512, # too small for complex JSON
messages=[...]
)
# After: give the model room to complete
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=4096, # generous budget for JSON completion
messages=[...]
)
A practical rule: estimate your maximum expected JSON size in tokens, then set max_tokens to 1.5x that. LLMs tokenize JSON at approximately 1 token per 3–4 characters.
Use Structured Output APIs
Grammar-constrained decoding makes missing brackets physically impossible. The FSM that governs token selection tracks the bracket stack — the model cannot emit a closing brace that mismatches, and the model cannot terminate without closing all open structures:
# Anthropic via tool use — JSON structure guaranteed complete
response = client.messages.create(
tools=[{"name": "result", "input_schema": schema}],
tool_choice={"type": "tool", "name": "result"},
messages=[...]
)
// OpenAI strict mode — bracket balance guaranteed
const response = await openai.chat.completions.create({
model: "gpt-5",
response_format: {
type: "json_schema",
json_schema: { name: "result", schema, strict: true }
},
messages: [...]
});
Add a Defensive Repair Wrapper
Even with structured output, add a repair wrapper as a last-resort catch:
from json_repair import repair_json
import json
def safe_json_parse(raw: str) -> dict:
"""Parse JSON with automatic repair on failure."""
try:
return json.loads(raw)
except json.JSONDecodeError as e:
try:
repaired = repair_json(raw)
result = json.loads(repaired)
# Log that repair was needed — indicates upstream issue
print(f"Warning: JSON required repair. Error was: {e}")
return result
except Exception:
raise ValueError(f"JSON could not be repaired: {raw[:200]}...")
Log every time repair is triggered. A rising repair rate signals that your max_tokens budget is too low or your prompt is not constraining output length effectively.
Missing Brackets vs Other JSON Errors
| Error | Example | Error Message | Fix |
|---|---|---|---|
| Missing closing bracket | {"tags": ["a", "b" | Unexpected end of JSON input | Add ]} |
| Missing opening bracket | "tags": "a", "b"] | Unexpected token ] | Structural — needs manual review |
| Mismatched brackets | {"tags": ["a"}} | Expected ',' or ']' | Replace }} with ]} |
| Trailing comma | {"name": "Alice",} | Unexpected token } | Remove trailing comma |
| Truncated mid-string | {"name": "Ali | Unterminated string | Close the string and structure |
The aijsonmedic.com repair tool handles all of these — including the truncated mid-string case, where it closes the string before adding the missing brackets.
FAQ
Q: Why doesUnexpected end of JSON input not tell me where the bracket is missing?
The parser reads JSON sequentially. When it reaches the end of the string, it knows the structure is incomplete — but by that point, it has already consumed the entire input. The useful location is where the unclosed bracket was opened, not where the string ended. To find the opening bracket, use the bracket balance counter or a repair tool that tracks the bracket stack.
Q: Can a repair tool reconstruct the correct data from truncated JSON?Partially. A repair tool can reconstruct the correct structure — closing all open brackets in the right order. It cannot reconstruct data that was never emitted (items cut off by the token limit never existed in the output). The repaired JSON is valid and parseable, but incomplete — you have everything the model output before truncation, and nothing after.
Q: My JSON has the right bracket count but still fails. Why?You may have mismatched brackets — the count is balanced (same number of [ and ]) but they don't match correctly. For example: {"a": ["b"}] has one [ and one ], and one { and one } — but } closes the [ and ] closes the {. Run the bracket balance counter above to find mismatches.
Safe to parse, but semantically incomplete. The repaired JSON contains only the data the model actually output. If you're processing a list of records and the model stopped mid-list, the repaired JSON has a shorter list than expected. Validate the count of records after repair if completeness matters for your use case.
Q: How does a repair tool know what closing brackets to add?It maintains a stack. When it sees {, it pushes } onto the stack. When it sees [, it pushes ]. When it sees a closing bracket, it pops from the stack. At end-of-input, any remaining items in the stack are the missing brackets — in reverse order. The repair appends them in that order.
For simple truncation at the end (not mid-value), you can use a minimal Python one-liner:
python3 -c "
import json, sys
from json_repair import repair_json
raw = sys.stdin.read()
print(json.dumps(json.loads(repair_json(raw))))
" < broken.json > fixed.json
Still dealing with broken JSON?
Paste it in and get it fixed in under 1 second — free, no signup, no install. Works with ChatGPT, Claude, n8n, and any AI output.
Fix My JSON Free →Related Articles