Tutorials

Debug Malformed JSON: 6 Common Syntax Errors & Quick Fixes

DevUtilHub Team
14 min read
Debug Malformed JSON: 6 Common Syntax Errors & Quick Fixes

How to Debug Malformed JSON: Common Syntax Errors and Quick Fixes

I’ll never forget the day I spent three hours debugging what I thought was a complex API integration issue, only to discover it was a missing comma in my JSON payload. Three hours. One comma. My teammate found it in about 30 seconds by pasting it into a formatter. That’s when I realized that JSON errors, while frustrating, follow predictable patterns—and once you know what to look for, you can spot them instantly.

JSON is everywhere in modern development. APIs spit it out, config files demand it, and databases store it. But here’s the thing: JSON is unforgiving. Unlike JavaScript, which might let you slide with trailing commas or single quotes, JSON has zero tolerance for deviation. One misplaced character and your entire payload becomes garbage. So let’s talk about how to actually debug this stuff efficiently, because we’ve all got better things to do than hunt for invisible Unicode characters at 2 AM.

Why JSON Breaks (And Why It’s Usually Simple)

Before we dive into specific errors, I want to share something that changed how I approach JSON debugging: most JSON errors fall into about five categories. That’s it. Once I started recognizing these patterns, my debugging time dropped dramatically.

The problem is that error messages from JSON parsers are often… unhelpful. “Unexpected token at position 247” doesn’t tell you much when you’re staring at 500 lines of nested objects. But if you know the common culprits, you can zero in on the problem fast.

The Most Common JSON Syntax Errors

1. Trailing Commas (The Silent Killer)

This one gets me more than I’d like to admit:

{
  "userName": "sarah_dev",
  "email": "[email protected]",
  "isActive": true,
}

See that comma after true? That’s invalid JSON. JavaScript lets you do this, so when you’re quickly converting JS objects to JSON, these sneak in. The fix is simple—remove it:

{
  "userName": "sarah_dev",
  "email": "[email protected]",
  "isActive": true
}

I’ve started using JSON Formatter whenever I’m manually writing JSON, because it catches these instantly. It’s saved me countless times when building request payloads for API testing.

2. Single Quotes Instead of Double Quotes

JSON is strict about quotes. Only double quotes work:

// WRONG - This will fail
{
  'productName': 'Wireless Mouse',
  'price': 29.99
}

// CORRECT
{
  "productName": "Wireless Mouse",
  "price": 29.99
}

This trips up developers coming from Python or JavaScript where single quotes are fine. I remember working with a junior dev who kept getting parse errors, and it turned out his text editor was auto-replacing double quotes with single quotes. Check your editor settings if this keeps happening to you.

3. Missing Commas Between Properties

When you’re building JSON by hand, especially complex nested structures, it’s easy to forget commas:

{
  "orderId": "ORD-2024-001"
  "customerName": "Alex Thompson"
  "items": [
    {
      "sku": "WIDGET-123"
      "quantity": 2
    }
  ]
}

Every property needs a comma after it (except the last one). Here’s the corrected version:

{
  "orderId": "ORD-2024-001",
  "customerName": "Alex Thompson",
  "items": [
    {
      "sku": "WIDGET-123",
      "quantity": 2
    }
  ]
}

4. Unescaped Special Characters in Strings

This one bit me hard when I was parsing user-generated content:

{
  "userBio": "I love coding and "breaking things" in production",
  "favoriteQuote": "It works on my machine \"
}

Those unescaped quotes will break your parser. You need to escape them with backslashes:

{
  "userBio": "I love coding and \"breaking things\" in production",
  "favoriteQuote": "It works on my machine \\"
}

Other characters that need escaping include backslashes (\\), newlines (\n), tabs (\t), and a few others. If you’re dealing with user input or content with special characters, always sanitize before converting to JSON.

5. Invalid Number Formats

JSON is picky about numbers. I once spent 20 minutes debugging this:

{
  "temperature": +23.5,
  "pressure": 1.013e+5,
  "altitude": 0x1F4,
  "coefficient": .5
}

The issues:

  • Leading + signs aren’t allowed
  • Hexadecimal notation isn’t supported
  • Numbers can’t start with a decimal point

Here’s the valid version:

{
  "temperature": 23.5,
  "pressure": 101300,
  "altitude": 500,
  "coefficient": 0.5
}

6. Comments (They Don’t Exist in JSON)

I know, I know—we all wish JSON supported comments. But it doesn’t:

{
  // This is the user's profile data
  "userId": "USR-789",
  /* 
    TODO: Add more fields here
  */
  "displayName": "Jordan"
}

If you need comments during development, use a JSON5 parser or keep them in separate documentation. For production JSON, strip them out completely.

My Go-To Debugging Strategy

When I encounter malformed JSON, here’s my exact process:

Step 1: Use a validator immediately. Don’t try to eyeball it. I paste suspicious JSON into JSON Formatter which shows me exactly where the error is and what’s wrong. This alone solves 80% of my JSON issues.

Step 2: Check for invisible characters. Copy the JSON to a plain text editor that shows whitespace. I’ve debugged JSON that had invisible Unicode characters (like zero-width spaces) that snuck in from copying content from web pages or PDFs.

Step 3: Validate piece by piece. If you have a huge JSON structure, comment out sections (in your source code, not in the JSON itself) and test incrementally. Binary search debugging works great here—remove half, test, narrow down.

Step 4: Check the source. If you’re receiving JSON from an API, check if it’s actually JSON. Sometimes APIs return error messages in HTML or plain text when things go wrong, and your JSON parser chokes on it.

Real-World Debugging Scenarios

Scenario 1: API Response Parsing Fails

I was integrating with a third-party API and kept getting parse errors. The API docs said it returned JSON, but my parser disagreed:

const apiResponse = await fetch('https://api.example.com/user/profile');
const userData = await apiResponse.json(); // Error: Unexpected token < in JSON

The problem? The API was returning a 500 error as HTML. I should have checked the response status first:

const apiResponse = await fetch('https://api.example.com/user/profile');

if (!apiResponse.ok) {
  const errorText = await apiResponse.text();
  console.error('API Error:', errorText);
  throw new Error(`API returned ${apiResponse.status}`);
}

const userData = await apiResponse.json();

Always validate the response before trying to parse it as JSON.

Scenario 2: Database JSON Column Contains Invalid Data

We had a PostgreSQL database with a JSON column that was supposed to store user preferences. One day, queries started failing:

SELECT preferences->>'theme' FROM users WHERE user_id = 12345;
-- ERROR: invalid input syntax for type json

Turns out someone had manually inserted data that wasn’t properly escaped. When dealing with JSON in databases, use the database’s JSON functions rather than string concatenation:

// WRONG - Vulnerable to JSON injection
const query = `INSERT INTO users (preferences) VALUES ('${JSON.stringify(userPrefs)}')`;

// CORRECT - Use parameterized queries
const query = 'INSERT INTO users (preferences) VALUES ($1)';
await db.query(query, [userPrefs]); // Let the driver handle serialization

Scenario 3: Configuration File Won’t Load

I once inherited a project where the config file was “JSON” but with comments and trailing commas everywhere:

{
  "apiEndpoint": "https://api.staging.example.com", // staging environment
  "timeout": 5000,
  "retries": 3,
}

The previous dev had been using a lenient parser that accepted this. When we upgraded dependencies, it broke. The solution was either switching to JSON5 or cleaning up the file. We went with cleanup and moved comments to a separate README.

Best Practices for Preventing JSON Errors

1. Never Hand-Write Complex JSON

Seriously, don’t do it. Generate JSON programmatically whenever possible:

const configData = {
  apiEndpoint: process.env.API_URL,
  timeout: 5000,
  features: {
    authentication: true,
    caching: false
  }
};

// This will always produce valid JSON
const jsonString = JSON.stringify(configData, null, 2);

2. Use Schema Validation

Don’t just check if JSON is syntactically valid—validate its structure too. I use JSON Schema for this:

import Ajv from 'ajv';

const ajv = new Ajv();
const schema = {
  type: 'object',
  properties: {
    email: { type: 'string', format: 'email' },
    age: { type: 'number', minimum: 0 }
  },
  required: ['email', 'age']
};

const validate = ajv.compile(schema);
const isValid = validate(userData);

if (!isValid) {
  console.error('Validation errors:', validate.errors);
}

This catches logical errors that syntax checking misses.

3. Set Up Proper Error Handling

When parsing JSON, always wrap it in try-catch:

function parseJSONSafely(jsonString) {
  try {
    return { success: true, data: JSON.parse(jsonString) };
  } catch (error) {
    console.error('JSON parse error:', error.message);
    // Log the actual string for debugging (be careful with sensitive data)
    console.debug('Failed to parse:', jsonString.substring(0, 200));
    return { success: false, error: error.message };
  }
}

4. Use Linters in Your Editor

Configure your editor to highlight JSON errors in real-time. VS Code does this out of the box. If you’re editing JSON files regularly, this is a game-changer.

5. Implement Request Logging

For APIs, log both the request and response bodies (with sensitive data redacted):

app.use((req, res, next) => {
  // Log incoming JSON payloads
  if (req.is('application/json')) {
    console.log('Incoming JSON:', JSON.stringify(req.body, null, 2));
  }
  next();
});

This helps you catch malformed JSON before it causes issues downstream.

6. Test with Edge Cases

Create a test suite with intentionally broken JSON:

const malformedExamples = [
  '{"missing": "closing brace"',
  '{"trailing": "comma",}',
  "{'single': 'quotes'}",
  '{"unescaped": "quote"s"}',
  '{duplicate: "duplicate", duplicate: "keys"}'
];

malformedExamples.forEach(example => {
  expect(() => JSON.parse(example)).toThrow();
});

7. Use Content-Type Headers Correctly

When sending JSON over HTTP, always set the correct header:

fetch('/api/users', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(userData)
});

Missing this header can cause servers to misinterpret your payload.

Common Mistakes to Avoid

Mistake 1: Assuming JavaScript Object Syntax Works

I spent way too long early in my career assuming that if it worked in JavaScript, it worked in JSON. JavaScript is more forgiving:

// Valid JavaScript, INVALID JSON
const jsObject = {
  name: "Sarah",        // Unquoted keys work in JS
  'email': "[email protected]",  // Single quotes work in JS
  active: true,         // This is fine in both
};

JSON requires quoted keys with double quotes. Period.

Mistake 2: Not Checking Response Content-Type

I once debugged for an hour because I assumed an endpoint returned JSON based on the documentation. It was actually returning XML with a 200 status. Always check:

const response = await fetch(apiUrl);
const contentType = response.headers.get('content-type');

if (!contentType || !contentType.includes('application/json')) {
  throw new Error(`Expected JSON, got ${contentType}`);
}

Mistake 3: Ignoring Encoding Issues

Different encodings can break JSON parsing. I encountered a file that looked fine but had BOM (Byte Order Mark) characters at the start:

function removeBOM(str) {
  return str.charCodeAt(0) === 0xFEFF ? str.slice(1) : str;
}

const cleanedJSON = removeBOM(fileContent);
const parsed = JSON.parse(cleanedJSON);

If you’re getting “Unexpected token” errors at position 0, check for BOM.

Mistake 4: Concatenating JSON Strings

Never, ever do this:

// WRONG - So many things can go wrong
const jsonString = '{"user": "' + userName + '", "role": "' + userRole + '"}';

If userName contains a quote, you’re toast. Always use JSON.stringify():

// CORRECT
const jsonString = JSON.stringify({ user: userName, role: userRole });

Mistake 5: Not Handling Large JSON Files Properly

I once tried to load a 500MB JSON file into memory and parse it all at once. My Node.js process crashed with an out-of-memory error. For large files, use streaming parsers:

import { parser } from 'stream-json';
import { streamArray } from 'stream-json/streamers/StreamArray';
import fs from 'fs';

const pipeline = fs.createReadStream('huge-file.json')
  .pipe(parser())
  .pipe(streamArray());

pipeline.on('data', ({ value }) => {
  // Process each item individually
  processItem(value);
});

Tools That Actually Help

Beyond the obvious JSON Formatter I mentioned earlier, here are some tools I keep handy:

When working with API responses that might be encoded, I’ll use a Base64 Decode tool to check if the response is base64-encoded JSON. Some APIs do this for binary safety.

For comparing JSON structures before and after transformations, a Code Diff Checker is invaluable. I use it constantly when refactoring data structures.

If you’re debugging JWT tokens (which are base64-encoded JSON), the JWT Debugger shows you the decoded payload and validates signatures—super helpful when authentication is failing.

When JSON Isn’t the Problem

Sometimes what looks like a JSON error is actually something else. I’ve debugged “JSON issues” that were actually:

  • CORS problems preventing the response from being read
  • Network timeouts causing incomplete responses
  • Rate limiting returning HTML error pages instead of JSON
  • Authentication failures redirecting to login pages
  • Proxy servers injecting content into responses

Always check the network tab in your browser’s dev tools to see what’s actually being sent and received.

Wrapping Up

JSON debugging doesn’t have to be painful. Most errors fall into predictable patterns: trailing commas, wrong quote types, missing commas, unescaped characters, or invalid numbers. Once you know what to look for, you can spot these in seconds.

My biggest piece of advice? Don’t try to debug JSON by staring at it. Use a formatter or validator immediately. I wasted hours in my early career trying to visually parse JSON when a tool could have found the error instantly.

And here’s the thing—these days, you shouldn’t be hand-writing much JSON anyway. Generate it programmatically, validate it with schemas, and test with real-world data including edge cases. Future you will thank present you for setting up proper validation and error handling now.

The three hours I spent on that missing comma taught me an important lesson: the right tools and knowledge of common patterns make all the difference. Now when I see a JSON error, I know exactly where to look and how to fix it fast.


Related Resources:

For more on data formats and debugging:

Frequently Asked Questions

Why does my JSON parse fine in JavaScript but fail in other languages?

JavaScript’s JSON.parse() is actually pretty strict and follows the JSON spec. However, if you’re creating objects in JavaScript without JSON.stringify(), you might be using JavaScript object syntax (unquoted keys, single quotes, trailing commas) which isn’t valid JSON. Always use JSON.stringify() to create actual JSON strings, then those will parse correctly in any language.

How can I find where my JSON is broken in a large file?

Use a JSON validator that shows line numbers and error positions. Most modern editors like VS Code will highlight JSON errors automatically. If the file is too large for manual inspection, use a JSON Formatter tool which will point you to the exact location of the error. You can also use command-line tools like jq which give detailed error messages with line numbers.

Can I use comments in JSON files for configuration?

Standard JSON doesn’t support comments at all. If you need comments in config files, consider using JSON5 (which supports comments and trailing commas) or switch to YAML or TOML for configuration. Many modern tools support these formats. Alternatively, keep a separate README file with documentation about your JSON config structure.

What’s the difference between undefined, null, and missing properties in JSON?

JSON doesn’t have an undefined value—only null. If a property is undefined in JavaScript and you stringify it, that property will be completely omitted from the JSON. A property with null value will be included as "property": null. A missing property simply isn’t present in the JSON object. This distinction matters when you’re expecting specific fields in your API responses.

How do I handle special characters and Unicode in JSON?

JSON natively supports Unicode, but certain characters must be escaped in strings: quotes (\"), backslashes (\\), and control characters like newlines (\n) and tabs (\t). When using JSON.stringify(), JavaScript handles this automatically. For other Unicode characters, you can either include them directly (if your file encoding is UTF-8) or use Unicode escape sequences like \u0041 for ‘A’.

Why does my API return valid JSON sometimes but fail other times?

This usually indicates conditional logic in your API that doesn’t handle all cases properly. Common causes include: returning HTML error pages instead of JSON when errors occur, incomplete error handling that crashes mid-response, timeout issues causing truncated responses, or different code paths that don’t all return properly formatted JSON. Add comprehensive logging and ensure all code paths return valid JSON, even error cases.

Tags

#JSON #debugging #syntax errors #API integration #web development

Share this article

Related Articles