<?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: Mark Foster</title>
    <description>The latest articles on DEV Community by Mark Foster (@devstone).</description>
    <link>https://dev.to/devstone</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%2F4163598%2F18a58086-b6ee-4657-8e85-fe74483847c6.png</url>
      <title>DEV Community: Mark Foster</title>
      <link>https://dev.to/devstone</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/devstone"/>
    <language>en</language>
    <item>
      <title>How to Fix the 10 Most Common YAML Errors</title>
      <dc:creator>Mark Foster</dc:creator>
      <pubDate>Mon, 12 Oct 2026 11:01:45 +0000</pubDate>
      <link>https://dev.to/devstone/how-to-fix-the-10-most-common-yaml-errors-33bn</link>
      <guid>https://dev.to/devstone/how-to-fix-the-10-most-common-yaml-errors-33bn</guid>
      <description>&lt;p&gt;YAML is easy to read and surprisingly easy to break. Its structure comes from indentation, many characters have special meanings, and a value that looks like a string can quietly become a boolean or a number. The result is a deploy that fails with &lt;code&gt;mapping values are not allowed here&lt;/code&gt;, or worse, a config that loads without any error but means something you did not intend.&lt;/p&gt;

&lt;p&gt;This guide covers the ten mistakes behind almost every YAML problem: what the error looks like, why it happens and how to fix it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Quickest fix:&lt;/strong&gt; paste the file into the &lt;a href="https://devbrace.com/yaml-validator" rel="noopener noreferrer"&gt;YAML Validator&lt;/a&gt;. It shows the exact line and column of the error, highlights the line, and warns about values that different parsers read differently.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Error messages below are quoted from two places: &lt;strong&gt;DevBrace&lt;/strong&gt; (the free &lt;a href="https://devbrace.com/yaml-validator" rel="noopener noreferrer"&gt;YAML Validator&lt;/a&gt; I built) and &lt;strong&gt;PyYAML&lt;/strong&gt;, the parser behind Ansible and most Python tools. Other parsers word things differently, but the causes are the same.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Tabs used for indentation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The YAML specification forbids tab characters for indentation, full stop. Editors that insert tabs, or copy-paste from a web page, are the usual culprits — and tabs are invisible, so the file looks fine.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DevBrace:&lt;/strong&gt; &lt;code&gt;Tabs are not allowed as indentation&lt;/code&gt; (line 2)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PyYAML:&lt;/strong&gt; &lt;code&gt;found character '\t' that cannot start any token&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; replace tabs with spaces. Set your editor to "insert spaces" for &lt;code&gt;.yaml&lt;/code&gt; and &lt;code&gt;.yml&lt;/code&gt; files. The &lt;a href="https://devbrace.com/yaml-formatter" rel="noopener noreferrer"&gt;YAML Formatter&lt;/a&gt; rewrites the whole file with consistent space indentation once it parses.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Inconsistent indentation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;example.com&lt;/span&gt;
   &lt;span class="s"&gt;port&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;host&lt;/code&gt; and &lt;code&gt;port&lt;/code&gt; are meant to be siblings, but &lt;code&gt;port&lt;/code&gt; has three spaces instead of two. To a YAML parser, a different indent means a different level of nesting, so the line no longer fits anywhere.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DevBrace:&lt;/strong&gt; &lt;code&gt;Nested mappings are not allowed in compact mappings&lt;/code&gt; (line 2)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; keys at the same level must start in exactly the same column. Two spaces per level is the convention for Kubernetes, Docker Compose, GitHub Actions and Ansible. When an error points to a line that looks correct, compare its indentation with the line above it.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. No space after the colon
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;name:api&lt;/span&gt;
&lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A key and its value are separated by a colon &lt;strong&gt;followed by a space&lt;/strong&gt;. Without the space, &lt;code&gt;name:api&lt;/code&gt; is not a key at all. The parser reads it together with the next line as one long key that spans two lines, which is not allowed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DevBrace:&lt;/strong&gt; &lt;code&gt;Implicit keys need to be on a single line&lt;/code&gt; (line 1)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; write &lt;code&gt;name: api&lt;/code&gt;. This is also why URLs work unquoted: in &lt;code&gt;url: https://example.com:8443/api&lt;/code&gt;, none of the colons inside the value are followed by a space.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. A colon followed by a space inside a value
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;message: Error&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;disk full&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first &lt;code&gt;:&lt;/code&gt; separates the key from the value. The second &lt;code&gt;:&lt;/code&gt; makes the parser think the value is itself a key, starting a nested mapping on a single line.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DevBrace:&lt;/strong&gt; &lt;code&gt;Nested mappings are not allowed in compact mappings&lt;/code&gt; (line 1, column 10)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PyYAML:&lt;/strong&gt; &lt;code&gt;mapping values are not allowed here&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; quote the value: &lt;code&gt;message: "Error: disk full"&lt;/code&gt;. Any value containing &lt;code&gt;:&lt;/code&gt; or &lt;code&gt;#&lt;/code&gt; (a space followed by a hash, which starts a comment) should be quoted.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. List items and keys mixed at the same level
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;apple&lt;/span&gt;
  &lt;span class="na"&gt;banana&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A node is either a list (&lt;code&gt;- item&lt;/code&gt;) or a mapping (&lt;code&gt;key: value&lt;/code&gt;), never both. Here &lt;code&gt;items&lt;/code&gt; starts as a list, then a key appears at the same indentation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DevBrace:&lt;/strong&gt; &lt;code&gt;All mapping items must start at the same column&lt;/code&gt; (line 3)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; decide what the data is. Either make every entry a list item:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;apple&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;banana&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or make &lt;code&gt;items&lt;/code&gt; a mapping with named keys. Converting the file with &lt;a href="https://devbrace.com/yaml-to-json" rel="noopener noreferrer"&gt;YAML to JSON&lt;/a&gt; is the fastest way to see which shape you actually wrote.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Unclosed quotes and brackets
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;world&lt;/span&gt;
&lt;span class="s"&gt;next:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;80&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;443&lt;/span&gt;
&lt;span class="nv"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;example.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A double-quoted string runs until the next unescaped &lt;code&gt;"&lt;/code&gt;, even across lines, and a flow list runs until its &lt;code&gt;]&lt;/code&gt;. One missing character swallows the rest of the file, so the reported line is often far below the real mistake.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DevBrace:&lt;/strong&gt; &lt;code&gt;Missing closing "quote&lt;/code&gt; and &lt;code&gt;Flow sequence in block collection must be sufficiently indented and end with a ]&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; close the quote or bracket. If the error line makes no sense, search upwards for the last &lt;code&gt;"&lt;/code&gt;, &lt;code&gt;'&lt;/code&gt;, &lt;code&gt;[&lt;/code&gt; or &lt;code&gt;{&lt;/code&gt; that was opened on the same logical value.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Duplicate keys
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
&lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;example.com&lt;/span&gt;
&lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The specification says keys in a mapping must be unique, but parsers disagree on what to do about it. PyYAML silently keeps the &lt;strong&gt;last&lt;/strong&gt; value, while JavaScript's &lt;code&gt;js-yaml&lt;/code&gt; and Go's &lt;code&gt;yaml.v3&lt;/code&gt; report an error. That means the same file can load in a Python script and fail in a Node or Go service — or load with a value you did not expect.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DevBrace:&lt;/strong&gt; &lt;code&gt;Map keys must be unique&lt;/code&gt; (line 3)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; remove or rename one of the keys. Duplicates usually appear after merging two versions of a file, so check the diff that introduced them.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Undefined aliases — and values starting with &lt;code&gt;*&lt;/code&gt; or &lt;code&gt;&amp;amp;&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;prod&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*defaults&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In YAML, &lt;code&gt;&amp;amp;name&lt;/code&gt; defines an anchor and &lt;code&gt;*name&lt;/code&gt; refers back to it. An alias must come &lt;strong&gt;after&lt;/strong&gt; its anchor, and the anchor must exist in the same document.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DevBrace:&lt;/strong&gt; &lt;code&gt;Unknown alias *defaults: no anchor &amp;amp;defaults is defined before it&lt;/code&gt; (line 2)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PyYAML:&lt;/strong&gt; &lt;code&gt;found undefined alias 'defaults'&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The same rule catches values that merely &lt;em&gt;look&lt;/em&gt; like aliases. &lt;code&gt;pattern: *.log&lt;/code&gt; is read as a reference to an anchor named &lt;code&gt;.log&lt;/code&gt;, not as a glob.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; define &lt;code&gt;&amp;amp;defaults&lt;/code&gt; above the alias, or quote text that starts with &lt;code&gt;*&lt;/code&gt; or &lt;code&gt;&amp;amp;&lt;/code&gt;: &lt;code&gt;pattern: "*.log"&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Values starting with a reserved character
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="s"&gt;jane&lt;/span&gt;
&lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Several characters cannot start a plain (unquoted) value: &lt;code&gt;@&lt;/code&gt; and &lt;code&gt;`&lt;/code&gt; are reserved, &lt;code&gt;{&lt;/code&gt; and &lt;code&gt;[&lt;/code&gt; start a flow mapping or list, &lt;code&gt;!&lt;/code&gt; starts a tag, &lt;code&gt;|&lt;/code&gt; and &lt;code&gt;&amp;gt;&lt;/code&gt; start a block scalar, and &lt;code&gt;%&lt;/code&gt; starts a directive.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DevBrace:&lt;/strong&gt; &lt;code&gt;Plain value cannot start with reserved character @&lt;/code&gt; (line 1)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The second line is subtler. &lt;code&gt;{ name }&lt;/code&gt; is valid YAML, but it is a mapping, not the text &lt;code&gt;{ name }&lt;/code&gt;. The same thing happens with the double-brace template expressions used by Ansible and Helm: an unquoted value that starts with a brace becomes a nested mapping, and PyYAML fails with &lt;code&gt;found unhashable key&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; quote the value: &lt;code&gt;email: "@jane"&lt;/code&gt;, &lt;code&gt;template: "{ name }"&lt;/code&gt;. Quote every template expression that starts a value.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Values that silently change type
&lt;/h2&gt;

&lt;p&gt;This one produces no error at all, which is what makes it dangerous.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;country&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NO&lt;/span&gt;
&lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
&lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0644&lt;/span&gt;
&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.10&lt;/span&gt;
&lt;span class="na"&gt;zip&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;02134&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;YAML 1.2 parsers&lt;/th&gt;
&lt;th&gt;YAML 1.1 parsers (PyYAML, Ruby)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;NO&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the string &lt;code&gt;"NO"&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;the boolean &lt;code&gt;false&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;yes&lt;/code&gt;, &lt;code&gt;on&lt;/code&gt;, &lt;code&gt;off&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;strings&lt;/td&gt;
&lt;td&gt;booleans&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0644&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the number 644&lt;/td&gt;
&lt;td&gt;the octal number 420&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;1.10&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the number 1.1&lt;/td&gt;
&lt;td&gt;the number 1.1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;02134&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the number 2134&lt;/td&gt;
&lt;td&gt;the octal number 1116&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;name:&lt;/code&gt; (nothing)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;null&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;null&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The first row is the famous &lt;strong&gt;Norway problem&lt;/strong&gt;: a list of country codes where Norway turns into &lt;code&gt;false&lt;/code&gt;. The &lt;code&gt;version: 1.10&lt;/code&gt; row bites everyone eventually — &lt;code&gt;1.10&lt;/code&gt; and &lt;code&gt;1.1&lt;/code&gt; are the same number, so the version you wrote is not the version your program reads.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://devbrace.com/yaml-validator" rel="noopener noreferrer"&gt;YAML Validator&lt;/a&gt; flags &lt;code&gt;NO&lt;/code&gt;, &lt;code&gt;yes&lt;/code&gt;, &lt;code&gt;off&lt;/code&gt; and &lt;code&gt;0644&lt;/code&gt; with a warning and the line number, because the file is valid but means different things to different tools.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; quote anything that must stay text: &lt;code&gt;country: "NO"&lt;/code&gt;, &lt;code&gt;version: "1.10"&lt;/code&gt;, &lt;code&gt;zip: "02134"&lt;/code&gt;. If you generate YAML from JSON, the &lt;a href="https://devbrace.com/json-to-yaml" rel="noopener noreferrer"&gt;JSON to YAML converter&lt;/a&gt; adds these quotes for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  A debugging checklist
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Validate first.&lt;/strong&gt; Paste the file into the &lt;a href="https://devbrace.com/yaml-validator" rel="noopener noreferrer"&gt;YAML Validator&lt;/a&gt; and go to the reported line.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Look above the reported line.&lt;/strong&gt; Indentation, unclosed quotes and missing colons are usually caused one or two lines earlier.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check for tabs.&lt;/strong&gt; Turn on "show whitespace" in your editor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quote suspicious values.&lt;/strong&gt; Anything with &lt;code&gt;:&lt;/code&gt;, &lt;code&gt;#&lt;/code&gt;, a leading &lt;code&gt;@&lt;/code&gt;, &lt;code&gt;*&lt;/code&gt;, &lt;code&gt;&amp;amp;&lt;/code&gt;, &lt;code&gt;{&lt;/code&gt;, &lt;code&gt;[&lt;/code&gt;, or a value like &lt;code&gt;yes&lt;/code&gt;, &lt;code&gt;no&lt;/code&gt;, &lt;code&gt;on&lt;/code&gt;, &lt;code&gt;off&lt;/code&gt;, version numbers and leading zeros.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;See what the parser sees.&lt;/strong&gt; Convert to JSON with &lt;a href="https://devbrace.com/yaml-to-json" rel="noopener noreferrer"&gt;YAML to JSON&lt;/a&gt;: the explicit brackets and quotes make wrong nesting and wrong types obvious.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Normalise the file.&lt;/strong&gt; Once it is valid, run it through the &lt;a href="https://devbrace.com/yaml-formatter" rel="noopener noreferrer"&gt;YAML Formatter&lt;/a&gt; so indentation stays consistent for the next person who edits it.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Catching YAML errors before they ship
&lt;/h2&gt;

&lt;p&gt;A validator in the browser is perfect while editing. In a repository, add a check to CI so a broken file never reaches production:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Syntax check with Python (PyYAML)&lt;/span&gt;
python &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'import sys, yaml; [list(yaml.safe_load_all(open(f))) for f in sys.argv[1:]]'&lt;/span&gt; config/&lt;span class="k"&gt;*&lt;/span&gt;.yaml

&lt;span class="c"&gt;# Style and syntax with yamllint&lt;/span&gt;
yamllint &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{extends: default, rules: {truthy: {check-keys: false}}}'&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;yamllint&lt;/code&gt;'s &lt;code&gt;truthy&lt;/code&gt; rule catches the Norway problem, its &lt;code&gt;key-duplicates&lt;/code&gt; rule catches duplicate keys, and &lt;code&gt;indentation&lt;/code&gt; catches the rest.&lt;/p&gt;

&lt;p&gt;Most YAML errors take seconds to fix once you know which of these ten you are looking at.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://devbrace.com/blog/fix-common-yaml-errors" rel="noopener noreferrer"&gt;DevBrace&lt;/a&gt;, where you can also try the &lt;a href="https://devbrace.com/yaml-validator" rel="noopener noreferrer"&gt;YAML Validator&lt;/a&gt; used in the examples.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>devops</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How to Fix the 8 Most Common JSON Errors</title>
      <dc:creator>Mark Foster</dc:creator>
      <pubDate>Mon, 05 Oct 2026 10:38:16 +0000</pubDate>
      <link>https://dev.to/devstone/how-to-fix-the-8-most-common-json-errors-25d2</link>
      <guid>https://dev.to/devstone/how-to-fix-the-8-most-common-json-errors-25d2</guid>
      <description>&lt;p&gt;&lt;code&gt;SyntaxError: Unexpected token } in JSON at position 212&lt;/code&gt; is one of the least helpful error messages a developer sees. It tells you &lt;em&gt;that&lt;/em&gt; the JSON is broken, but not &lt;em&gt;why&lt;/em&gt;, and the position is a character offset you have to count to.&lt;/p&gt;

&lt;p&gt;The good news: almost every JSON error comes from the same short list of mistakes. This guide covers the eight you will hit most often, what the error looks like in JavaScript and Python, and how to fix each one.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Quickest fix:&lt;/strong&gt; paste your JSON into the &lt;a href="https://devbrace.com/json-validator" rel="noopener noreferrer"&gt;JSON Validator&lt;/a&gt;. It names the mistake in plain English, shows the exact line and column, and highlights the broken line.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why JSON is so strict
&lt;/h2&gt;

&lt;p&gt;JSON looks like a JavaScript object literal, but it is a much smaller language. The &lt;a href="https://www.rfc-editor.org/rfc/rfc8259" rel="noopener noreferrer"&gt;specification (RFC 8259)&lt;/a&gt; allows only:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;objects &lt;code&gt;{}&lt;/code&gt; with &lt;strong&gt;double-quoted&lt;/strong&gt; string keys,&lt;/li&gt;
&lt;li&gt;arrays &lt;code&gt;[]&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;strings in &lt;strong&gt;double quotes&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;numbers, &lt;code&gt;true&lt;/code&gt;, &lt;code&gt;false&lt;/code&gt; and &lt;code&gt;null&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's it. No comments, no trailing commas, no single quotes, no &lt;code&gt;undefined&lt;/code&gt;. Being strict is what makes JSON portable — every language parses it the same way — but it means small habits from JavaScript or Python break it.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Trailing commas
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Jane"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;JavaScript, TypeScript and Python all allow a comma after the last item. JSON does not.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;JavaScript:&lt;/strong&gt; &lt;code&gt;Expected double-quoted property name in JSON at position 41 (line 4 column 1)&lt;/code&gt; in current Chrome and Node.js; older engines say &lt;code&gt;Unexpected token } in JSON&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Python:&lt;/strong&gt; &lt;code&gt;json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; remove the comma after the last property or array item.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Single quotes
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'name':&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'Jane'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Strings and keys must use double quotes (&lt;code&gt;"&lt;/code&gt;). Single quotes are the most common mistake when JSON is typed by hand or copied from Python's &lt;code&gt;print()&lt;/code&gt; of a dict.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; replace &lt;code&gt;'&lt;/code&gt; with &lt;code&gt;"&lt;/code&gt;. If you are producing JSON from Python, use &lt;code&gt;json.dumps(data)&lt;/code&gt; instead of &lt;code&gt;str(data)&lt;/code&gt; — &lt;code&gt;str()&lt;/code&gt; prints Python syntax, not JSON.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Unquoted keys
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;name:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Jane"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;age:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Valid JavaScript, invalid JSON. Every key must be a double-quoted string.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; wrap each key in double quotes: &lt;code&gt;{ "name": "Jane", "age": 31 }&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Missing commas
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Jane"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"admin"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Usually caused by adding a new line to an existing object and forgetting the comma on the line above. The parser reports the error on the &lt;em&gt;second&lt;/em&gt; line, which is confusing — the mistake is really at the end of the line before.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; add a comma after &lt;code&gt;"Jane"&lt;/code&gt;. When an error points to the start of a line, always check the end of the previous line first.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Comments
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;database&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;settings&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"localhost"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;JSON has no comment syntax. Some tools accept “JSONC” (JSON with comments) — VS Code's &lt;code&gt;settings.json&lt;/code&gt; and &lt;code&gt;tsconfig.json&lt;/code&gt; are examples — but a standard parser like &lt;code&gt;JSON.parse&lt;/code&gt; will reject it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; remove the comments. If your config needs comments, consider YAML or TOML instead — see &lt;a href="https://devbrace.com/json-to-yaml" rel="noopener noreferrer"&gt;JSON to YAML&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Python and JavaScript values that aren't JSON
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"manager"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;NaN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"extra"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;undefined&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Not JSON&lt;/th&gt;
&lt;th&gt;Use instead&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;True&lt;/code&gt; / &lt;code&gt;False&lt;/code&gt; (Python)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;true&lt;/code&gt; / &lt;code&gt;false&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;None&lt;/code&gt; (Python)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;null&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;undefined&lt;/code&gt; (JavaScript)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;null&lt;/code&gt;, or leave the key out&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;NaN&lt;/code&gt;, &lt;code&gt;Infinity&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;null&lt;/code&gt;, or a string like &lt;code&gt;"NaN"&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;NaN&lt;/code&gt; is a sneaky one: Python's &lt;code&gt;json.dumps&lt;/code&gt; writes &lt;code&gt;NaN&lt;/code&gt; by default, producing output that other parsers (including JavaScript's) reject. Pass &lt;code&gt;allow_nan=False&lt;/code&gt; to catch it early.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Unescaped characters inside strings
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;ew&lt;/span&gt;&lt;span class="se"&gt;\f&lt;/span&gt;&lt;span class="s2"&gt;older"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"quote"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"She said "&lt;/span&gt;&lt;span class="err"&gt;hi&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside a JSON string, a backslash starts an escape sequence and a double quote ends the string. So &lt;code&gt;\n&lt;/code&gt; becomes a newline, &lt;code&gt;\f&lt;/code&gt; a form feed — and &lt;code&gt;"hi"&lt;/code&gt; closes the string early.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; escape backslashes as &lt;code&gt;\\&lt;/code&gt; and quotes as &lt;code&gt;\"&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C:&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;new&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;folder"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"quote"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"She said &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;hi&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Literal line breaks and tabs inside a string are also invalid; use &lt;code&gt;\n&lt;/code&gt; and &lt;code&gt;\t&lt;/code&gt;. The &lt;a href="https://devbrace.com/json-escape" rel="noopener noreferrer"&gt;JSON Escape tool&lt;/a&gt; converts any text into a correctly escaped JSON string.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. The response isn't JSON at all
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SyntaxError: Unexpected token '&amp;lt;', "&amp;lt;!DOCTYPE "... is not valid JSON
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Older engines: &lt;code&gt;Unexpected token &amp;lt; in JSON at position 0&lt;/code&gt;.) If the first character is &lt;code&gt;&amp;lt;&lt;/code&gt;, you are not parsing JSON — you are parsing an HTML page. Typical causes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the URL is wrong and the server returned a 404 page,&lt;/li&gt;
&lt;li&gt;your session expired and you were redirected to a login page,&lt;/li&gt;
&lt;li&gt;the server crashed and returned an HTML error page.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; log the raw response before parsing it, and check the status code and &lt;code&gt;Content-Type&lt;/code&gt; header:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`HTTP &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content-type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Expected JSON, got &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="p"&gt;${(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A similar case is &lt;code&gt;Unexpected end of JSON input&lt;/code&gt;, which means the text was empty or cut off — often an empty response body from a &lt;code&gt;204 No Content&lt;/code&gt; or a request that timed out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Errors that aren't syntax errors
&lt;/h2&gt;

&lt;p&gt;Some JSON parses fine but still causes bugs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Duplicate keys:&lt;/strong&gt; &lt;code&gt;{"role": "user", "role": "admin"}&lt;/code&gt; is accepted by most parsers, which silently keep the last value.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Big numbers:&lt;/strong&gt; integers above 9,007,199,254,740,991 (2&lt;sup&gt;53&lt;/sup&gt; − 1) lose precision in JavaScript. &lt;code&gt;1234567890123456789&lt;/code&gt; becomes &lt;code&gt;1234567890123456800&lt;/code&gt; after &lt;code&gt;JSON.parse&lt;/code&gt;. Send large IDs as strings.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;a href="https://devbrace.com/json-validator" rel="noopener noreferrer"&gt;JSON Validator&lt;/a&gt; warns about both, even when the syntax is valid.&lt;/p&gt;

&lt;h2&gt;
  
  
  A debugging checklist
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Validate the text and go to the reported line.&lt;/li&gt;
&lt;li&gt;If the error is at the start of a line, check the &lt;strong&gt;end of the previous line&lt;/strong&gt; (missing comma).&lt;/li&gt;
&lt;li&gt;If the error mentions &lt;code&gt;&amp;lt;&lt;/code&gt; or &lt;code&gt;&amp;lt;!DOCTYPE&lt;/code&gt;, you received HTML — check the request, not the JSON.&lt;/li&gt;
&lt;li&gt;Search for &lt;code&gt;'&lt;/code&gt;, &lt;code&gt;//&lt;/code&gt;, &lt;code&gt;True&lt;/code&gt;, &lt;code&gt;None&lt;/code&gt;, &lt;code&gt;NaN&lt;/code&gt; and &lt;code&gt;undefined&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Once it parses, &lt;a href="https://devbrace.com/json-formatter" rel="noopener noreferrer"&gt;format it&lt;/a&gt; so the structure is easy to review.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Most JSON errors take seconds to fix once you know which of these eight you are looking at.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://devbrace.com/blog/fix-common-json-errors" rel="noopener noreferrer"&gt;devbrace.com&lt;/a&gt;. DevBrace is a set of free developer tools that run entirely in your browser.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>json</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
