# YAML? That's Norway Problem

> Source: <https://lab174.com/blog/202601-yaml-norway/>
> Published: 2026-05-21 04:18:53+00:00

2026-01-12

Yaml is a well-known data serialization language designed for human readability. It’s a popular choice for configuration files and metadata. Here’s a simple example:

```
# project.yaml

title: Nonoverse
description: Beautiful puzzle game about nonograms.
link: https://lab174.com/nonoverse
countries:
  - DE
  - FR
  - PL
  - RO
```

Let’s verify that the above example parses correctly.

We’ll use Python[ 1](#fn1) with PyYaml

```
python3 -m pip install pyyaml==6.0.3
```

Now let’s write a simple script to parse the yaml file:

``` python
# python-pyyaml.py

import json
import yaml

with open("project.yaml", "r", encoding="utf-8") as f:
    data = yaml.safe_load(f)

print(json.dumps(data, indent=2))
```

Running `python3 python-pyyaml.py`

produces this
output:

```
{
  "title": "Nonoverse",
  "description": "Beautiful puzzle game about nonograms.",
  "link": "https://lab174.com/nonoverse",
  "countries": [
    "DE",
    "FR",
    "PL",
    "RO"
  ]
}
```

So far everything behaves as expected.

When we change the original yaml file and add Norway’s two letter iso country code to the existing list:

```
countries:
  - DE
  - FR
  - NO
  - PL
  - RO
```

Using the same parsing method, the file now yields this result:

```
{
  "title": "Nonoverse",
  "description": "Beautiful puzzle game about nonograms.",
  "link": "https://lab174.com/nonoverse",
  "countries": [
    "DE",
    "FR",
    false,
    "PL",
    "RO"
  ]
}
```

Note that `NO`

has been replaced with `false`

.
This is unexpected. Nothing about the context suggests a boolean should
appear here. The `NO`

literal sits in a list of country codes
like `FR`

or `PL`

and appears similar in form. The
problem, of course, is that “no” is also an English word with a negative
meaning.

This feature was originally added to allow writing booleans in a more human readable way, e.g.:

```
platforms:
  iPhone: yes
  iPad: yes
  AppleWatch: no
```

This gets parsed as:

```
{
  "platforms": {
    "iPhone": true,
    "iPad": true,
    "AppleWatch": false
  }
}
```

The idea was that configuration files should read like natural language. In practice this behavior proved problematic, becoming the notorious Norway problem in yaml.

One workaround is to escape the string, like this:

```
countries:
  - DE
  - FR
  - "NO"
  - PL
  - RO
```

With quotes, the file parses as expected:

```
{
  "title": "Nonoverse",
  "description": "Beautiful puzzle game about nonograms.",
  "link": "https://lab174.com/nonoverse",
  "platforms": {
    "iPhone": true,
    "iPad": true,
    "AppleWatch": false
  },
  "countries": [
    "DE",
    "FR",
    "NO",
    "PL",
    "RO"
  ]
}
```

Many articles about yaml’s Norway problem stop here, presenting quoting as the canonical fix. There is more.

To understand today’s state of the Norway problem we’ll first look at how yaml evolved.

At this time, yaml was more of a concept than a finished language. It looked a bit different, though somewhat recognizable. Below is a partial example from the original specification; there are more in the full document, sadly none with boolean values.

```
buyer    : %
    address     : %
       city       : Royal Oak
       line one   : 458 Wittigen's Way
       line two   : Suite 292
       postal     : 48046
       state      : MI
    family name : Dumars
    given name  : Chris
```

The document makes no mention of parsing `no`

to
`false`

. The “Serilization Format / bnf” section even contains a typo and a “to do”
note[ 3](#fn3):

This section contains the bnf

[productions for the yaml syntax. Much to do…]4

This version describes various ways of presenting scalars[ 5](#fn5), including both quoted scalars and
plain scalars with implicit typing. This is what we’re after.

Version 1.0 defined only `sequence`

, `map`

, and
`string`

as mandatory types[ 6](#fn6).
The rest were optional, but a reference specification existed. That
reference specification for the optional boolean type included English
word format. Supported words were:

`true/false`

,
`on/off`

, and also `yes/no`

This allows the Norway problem to appear – even if following that part of reference is described as optional.

– Bonus: implicit typing can be overridden with explicit tags – we’ll talk about this later.

– Bonus: single sign characters, i.e. `+`

and
`-`

should also be treated as `true`

and
`false`

; even more so, as they are described as the canonical
form[ 8](#fn8)!

Version 1.1 maintained the same implicit typing behavior as v1.0.
However, the types listed in the spec – including boolean – while still
not mandatory, were now strongly recommended[ 9](#fn9).

– Bonus: single sign characters are no longer included and the
canonical form is now `y/n`

[ 10](#fn10).

Its goal was to make yaml compliant
with json, going as far as allowing json to be a subset of yaml[ 11](#fn11).

**Implicit typing rules have been removed, including the
boolean English word format.**

– Bonus: explicit typing rules are still present.

On paper, the Norway problem shouldn’t exist anymore, at least not since this yaml revision. So why are we still seeing it in 2026?

| Yaml spec version | Date | Type of `no` : |
Value of `no` |
|---|---|---|---|
| first pass specification | May 2001 | unspecified | unspecified |
| v1.0 | January 2004 | boolean | `false` |
| v1.1 | January 2005 | boolean | `false` |
| v1.2.0 | July 2009 | string | `"no"` |

`no`

” and “Value of `no`

”
labels refer to the literal without quotes.
To understand why the Norway problem persists, we need to examine the scope of work involved in implementing yaml spec changes. Some clues are present in earlier text already, we see that yaml supports implicit typing, explicit typing, and various presenting formats. Also, the time between different yaml spec version releases is measured in years.

What hides between the lines is that yaml and its specification are very, hugely,
**extremely** complex. Seriously, it’s hard to overstate
this.

Since v1.0 yaml’s goal was to build
upon xml[ 12](#fn12)
and a number of other technologies, as listed in the final draft

Yaml integrates and builds upon concepts described by C, Java, Perl, Python, Ruby, rfc0822 (mail), rfc1866 (html), rfc2045 (mime), rfc2396 (uri), xml, sax and soap

Yaml supports attachments, custom
tags, references – the list goes on. There was even yaxml, an xml
binding for yaml[ 14](#fn14).
There are 9 ways of writing multiline strings – and some claim the
number is actually 63

`?`

,
`!`

, `!!`

in some cases have special meanings,
with the latter allowing arbitrary code execution.Given this complexity, the Norway problem wasn’t the only language quirk in yaml v1.1. Revision v1.2 simplified boolean behavior and more (e.g. handling of null and numerical values), while other language features remained unchanged.

How did libraries react to changes in such a complex specification?

As of January 2026 popular yaml libraries still haven’t moved from v1.1 to v1.2, and they still exhibit the Norway problem. Smaller alternative projects have appeared, but their usage hasn’t surpassed the existing v1.1 libraries. Some users have built their own alternative parsers, mixing v1.1 and v1.2 features, or focusing on a subset of yaml suited to their needs.

Below are some examples.

As mentioned before, PyYaml is Python’s most popular yaml library and one of the most popular Python libraries overall.

PyYaml never added v1.2 support.

There is an open issue from 2017 in PyYaml’s Github project about introducing support
for v1.2[ 16](#fn16). There are at least two more
related open issues, plus several closed ones. An unofficial library

LibYaml is the long-standing C library for yaml, it is used widely as a dependency by other tools and bindings. Like PyYaml, it’s an “official” implementation – in the sense that its canonical repository is hosted on Github and owned by the official ‘yaml’ Github account.

LibYaml also never added v1.2 support.

An open issue from 2016 in LibYaml’s
github project requests adding v1.2 support[ 19](#fn19).
As mentioned earlier, LibYaml sits deep
in dependency trees; changing its behavior is especially risky and slow.
A less popular library, libfyaml

Currently unmaintained[ 21](#fn21), historically the most
popular and still holds more Github stars then other Golang yaml libraries. It’s especially interesting
because it declares support for a mix of v1.1 and 1.2

Kyaml is a yaml dialect built for the Kubernetes project,
launched in June 2025. Its goal is to provide a safer and less ambiguous
tool; it is also designed specifically for Kubernetes, trading
generality for predictability. The announcement blog post references the
Norway problem directly[ 24](#fn24).

Yaml’s ecosystem is not just libraries, it’s also the community of users. Including: strong and conflicting opinions about yaml in general and the Norway problem in particular.

In some part this outcome could be expected; after all yaml is very popular, deceptively complex, and is used in different kinds of scenarios, from small personal config files to critical infrastructure setups.

Many texts don’t distinguish between yaml spec versions at all[ 25](#fn25).
Even when spec version numbers are used, they’re frequently mistyped.
It’s not difficult to find documentation claiming that implicit boolean
typing is a trait of yaml specification
version 1.2

On the other hand we see users who declare the Norway problem as
solved because it doesn’t exist in the latest spec version, or because
they haven’t experienced it themselves, or for other reasons[ 28](#fn28). To be fair, that language feature
was removed over a decade ago, and it’s unexpected that popular
libraries still support the older spec version. Technically, the issue
is solved in the spec – but in practice, most widely adopted
implementations still support implicit boolean typing, as we’ve
seen.

Finally, there are end users who are so unhappy with yaml that they prefer almost anything else[ 29](#fn29).

We end up with countless use cases (hobby, pro, critical infrastructure, …), roles (spec author, library maintainer, end user debugging a failed deployment at 11pm, …), and just as many points of views.

In yaml final draft v1.0, the document
specified that, along with `yes`

and `no`

,
`+`

and `-`

should also be parsed as booleans.
This was removed v1.1. There was an idea to keep that functionality when
plus or minus signs were preceded with a dot (`.+`

and
`.-`

), but it didn’t catch on.

Despite its well known and lesser known quirks, yaml remains popular and widely used. At this scale small quirks cascade into unexpected issues. And changes – or fixes – are introduced at a glacial pace.

Then again, yaml’s charm has its place, as evidenced by its popularity. While spec change adoption is very slow, it is still ongoing. New projects will likely adopt newer libraries, where the Norway problem no longer exists.

If there is a single takeaway from this article, it’s this: yaml ecosystem is fragmented; on the whole it is moving towards a slightly stricter version. Implicit boolean typing is getting removed, it’s no longer in the official specification and most new libraries adhere to that. As of January 2026 however, the older libraries are stuck on the older version of the spec, they are still more popular and updating or phasing them out may take a while.

A common reply is “no comments” – because json doesn’t support comments[ 30](#fn30);
many other yaml features aren’t supported
either. This makes json a simpler and
stricter alternative. Wheter that’s a better fit for your project, that
depends on the project. As always, personal preference plays a role too.
Note: json has its own flavors, like
jsonc

After writing this article, I’m still not entirely sure. Even though
the goal of yaml revision v1.2.0 was to
make that happen and revisions 1.2.0 and 1.2.1 claimed it explicitly[ 32](#fn32):

Yaml can therefore be viewed as a natural superset of json, offering improved human readability and a more complete information model.

That text has been removed from the latest yaml revision 1.2.2.

A popular article[ 33](#fn33) claims to prove that yaml is not a superset of json, but that article uses a v1.1 parser – and
as we know v1.1 never claimed json
compatibility. So that won’t help us.

The actual reason might be that yaml
requires maps to have unique keys[ 34](#fn34), while json only recommends it

This question is out of scope for this article – here the goal is to prioritize facts over “what if?”.

If i had to answer, I’d say that nothing went wrong. When a complex technology with a stable ecosystem introduces a breaking change, sometimes the process can take ages. The main surprise here is how complicated yaml really is. Also, as we’ve seen, with yaml and related tools being free software, anyone could contribute to improving the v1.2 adoption rate – or move to a tool that suits them better, or even create one.

These topics are only loosely related to the Norway problem, and this
text is already quite long. If you enjoyed reading it, leave positive
feedback somewhere and a Part 2 might happen. In the meantime, visit my
homepage[ 36](#fn36) and check out my other projects –
maybe you’ll find something else you’ll enjoy.

Implicit boolean typing has been removed, but explicit boolean typing still remains. If a uniform yaml 1.2 future actually arrives, you can still bring a little bit of nostalgia to your code by writing:

```
title: Nonoverse
description: Beautiful puzzle game about nonograms.
link: https://lab174.com/nonoverse
platforms:
  iPhone: !!bool yes
  iPad: !!bool yes
  # Note the explicit typing here and above.
  AppleWatch: !!bool no
countries:
  - DE
  - FR
  - NO
  - PL
  - RO
```

When parsed with `yq`

, a tool that supports yaml revision 1.2 by default:

`yq eval -o=json project.yaml`

It returns:

```
{
  "title": "Nonoverse",
  "description": "Beautiful puzzle game about nonograms.",
  "link": "https://lab174.com/nonoverse",
  "platforms": {
    "iPhone": true,
    "iPad": true,
    "AppleWatch": false
  },
  "countries": [
    "DE",
    "FR",
    "NO",
    "PL",
    "RO"
  ]
}
```


