LmCast :: Stay tuned in

YAML? That's Norway Problem

Recorded: May 23, 2026, midnight

Original Summarized

YAML? That’s Norway problem

< Back to LAB174.com

YAML? That’s Norway problem
2026-01-12

Abstract
A deep dive into YAML’s Norway problem: why the country code NO gets
parsed as false, its history from YAML v1.0 to v1.2, and why popular
libraries still exhibit this behavior in 2026.

What is yaml
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 Python1 with PyYaml2 version 6.0.3 (the
latest version as of this writing). First, let’s install it:
python3 -m pip install pyyaml==6.0.3
Now let’s write a simple script to parse the yaml file:
# 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.

As of January 2026 Python is the world’s 4th most
popular programming language according to a 2025
Stack Overflow Survey (archive)↩︎
PyYaml is Python’s most
popular yaml library and a top 20 Python
library overall in the last month according to PyPI Stats (archive).
It is also an “official” yaml library in
the sense that its source code is hosted in a Github repository owned by
the yaml Github account; see: Canonical source repository for
PyYaml.↩︎

The Norway problem in yaml
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.
Yaml’s
history
To understand today’s state of the Norway problem we’ll first look at
how yaml evolved.
May 2001 – Yaml first pass specification
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”
note3:

This section contains the bnf4 productions for the yaml syntax. Much to do…

Full
first pass specification – archived link↩︎
Bnf stands for
“Backus–Naur form”, a notation system for syntax definition (Wikipedia).↩︎

January 2004 – Yaml v1.0 final draft
This version describes various ways of presenting scalars5, 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 types6.
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/no7.
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
form8!

A scalar data type, or just scalar, is any non-composite value.
Generally, all basic primitive data types are considered scalar

source: Wikipedia↩︎

Following is a description of the three mandatory core tags. Yaml requires support for the seq, map and str
tags.

source: Yaml v1.0 specification, tag repository↩︎
English word format:
implicit english ~= true|True|TRUE
|false|False|FALSE
|yes|Yes|YES
|no|No|NO
|on|On|ON
|off|Off|OFF
source: Yaml v1.0 boolean type specification – archived
link↩︎
Single sign character format:
implicit canonical ~= +|-
source: Yaml v1.0 boolean type specification – archived
link↩︎

January 2005 – Yaml v1.1 final draft
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 recommended9.
– Bonus: single sign characters are no longer included and the
canonical form is now y/n10.

these tags represent types that are useful across a wide range of
applications and it is strongly recommended they be used whenever
appropriate to promote interoperability.

source: Yaml v1.1 specification, tag repository (archive)↩︎
Yaml v1.1 boolean type specification, (archive)↩︎

July 2009 – Yaml Revision 1.2.0
Its goal was to make yaml compliant
with json, going as far as allowing json to be a subset of yaml11.
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?

The primary objective of this revision is to bring Yaml into compliance with json as an official subset.

source: Yaml revision v1.2.0↩︎

Yaml spec version history until v1.2.0

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"

Table 1: Summary of yaml spec changes.
Note that “Type of no” and “Value of no”
labels refer to the literal without quotes.

Yaml in
practice
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 xml12
and a number of other technologies, as listed in the final draft13:

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 yaml14.
There are 9 ways of writing multiline strings – and some claim the
number is actually 6315. Characters like ?,
!, !! 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?

In fact yaml was
originally intended to be a markup language and its name stood for “Yet
Another Markup Language”. Six months after the first pass specification,
in January 2002, it was renamed to “Yaml
Ain’t Markup Language”.↩︎
Yaml v1.0 specification, prior art↩︎

a subset of xml which has yaml’s information model, but xml’s syntax (…) a xslt Stylesheet is provided, along with the
canonical invoice example in xml using
this schema

source: Yaxml, the (draft) xml Binding for yaml – archived link↩︎

There are 5 6 NINE (or 63, depending how you
count) different ways to write multi-line strings in yaml. (…) 2 block styles, each with 2 possible
block chomping indicators (or none), and with 9 possible indentation
indicators (or none), 1 plain style and 2 quoted styles: 2 x (2 + 1) x
(9 + 1) + 1 + 2 = 63

source: Stack Overflow
answer (archived)↩︎

Yaml
libraries
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.
PyYaml
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.216. There are at least two more
related open issues, plus several closed ones. An unofficial library17 exists that can be used on top of
PyYaml to provide partial v1.2 support
(its documentation notes that not all v1.2 features are implemented).
Another Python library, ruamel.yaml18, supports v1.2 by
default.

PyYaml Github Issue #116↩︎
yamlcore
PyPI project page↩︎
ruamel.yaml PyPI project
page↩︎

LibYaml
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 support19.
As mentioned earlier, LibYaml sits deep
in dependency trees; changing its behavior is especially risky and slow.
A less popular library, libfyaml20, supports v1.2 by
default.

LibYaml Github Issue #20↩︎
libfyaml Github project
page↩︎

Golang’s gopkg.in/yaml.v3
Currently unmaintained21, 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.222.
The Golang’s most popular actively maintained library23
defaults to v1.2 behavior.

“This project is unmaintained”, source: gopkg.in/yaml.v3
Github project page↩︎
“The yaml package supports most of yaml 1.2, but preserves some behavior from 1.1
for backwards compatibility.”, source: gopkg.in/yaml.v3
Github project page↩︎
goccy/go-yaml Github project
page↩︎

Kyaml
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 directly24.

Yaml’s significant whitespace requires
careful attention to indentation and nesting, while its optional
string-quoting can lead to unexpected type coercion (for example: “The
Norway Bug”).

source: Kubernetes
v1.34 Sneak Peek↩︎

Is the Norway problem solved?
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 all25.
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.226 (the correct version is v1.1);
mistakes get spotted27 and eventually updated, but that
takes more time and effort than making the original typo.
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 reasons28. 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 else29.
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.

The yaml specification defines many
strings that are automatically interpreted as boolean values, which
often conflicts with developer expectations. When you write
country: NO, the yaml parser
interprets NO as the boolean false, not the
string "NO"

source: What is
the Norway Bug?↩︎

The most tragic aspect of this bug , however, is that it is intended
behavior according to the yaml 1.2
specification.

source: The
Norway Problem – why StrictYaml refuses
to do implicit typing and so should you↩︎
In this case a Github issue has been created:

It was intended according to the yaml
1.1 specification, but in yaml 1.2, the
only
recognized booleans are true, True,
TRUE, false, False,
FALSE.

source: strictyaml
Github issue #186↩︎
I don’t want to link to individual messages on social
platforms to err on the side of users’ privacy; I’ll paraphrase some of
them below, for illustration purposes.
Norway problem has been solved for 16 years.
Using 1.1 at this point is just forehead palming foolishness.
The Norway issue is a bit blown out of proportion.
I have been using YAML for 5+ years and have never had it.
We stopped having this problem over ten years ago.
Just quote your strings.
Another solution is to change the country name.
↩︎
Same as earlier, I’ll paraphrase a few messages below,
meant for illustration.
Stop using YAML
YAML - just say Norway.
You should stop even tolerating YAML, refuse on sight.
YAML made sense before JSON became a thing.
YAML made me look at XML wistfully.
Why people persist with YAML in new projects is baffling to me.
People from Norway couldn't sign up. Took us a while to figure out.
↩︎

What next?
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.
Frequently Asked Questions
Why not just use json in place of yaml?
A common reply is “no comments” – because json doesn’t support comments30;
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
jsonc31.

It was a conscious decision; there is an explanation
from Douglas Crockford, as well as a suggestion about using json for configuration files:

I removed comments from json because I
saw people were using them to hold parsing directives, a practice which
would have destroyed interoperability. I know that the lack of comments
makes some people sad, but it shouldn’t.

Suppose you are using json to keep
configuration files, which you would like to annotate. Go ahead and
insert all the comments you like. Then pipe it through JSMin before
handing it to your json parser.

source: Google
Plus post by Douglas Crockford – archived link↩︎
Json with Comments – project’s homepage↩︎

Is yaml a superset of json?
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 explicitly32:

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 article33 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 keys34, while json only recommends it35.
So perhaps most json (i.e. json where objects have unique keys) is a
subset of yaml. Some ambiguity
remains.

See e.g.: Yaml Version 1.2 Revision 1.2.1↩︎

Json treats the value 1e2 a number, of
course, because it’s not in quote marks. Yaml fails to parse it as a number so silently
falls back to treating it as a string.

source: YAML
IS NOT A SUPERSET OF JSON↩︎

The content of a mapping node is an unordered set of key/value node
pairs, with the restriction that each of the keys is unique

source: Yaml Version 1.2 Revision 1.2.2↩︎

The names within an object SHOULD be unique.

source: The
application/json Media Type for JavaScript Object Notation (json)↩︎

What went wrong?
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.
What
about toml, sexagesimal numbers, schemas,
human genes, Ruby, or Perl?
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
homepage36 and check out my other projects –
maybe you’ll find something else you’ll enjoy.

LAB174 homepage↩︎

Epilogue
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"
]
}

< Back to LAB174.com

YAML is a data serialization language designed for human readability, making it a popular choice for configuration files and metadata. The core issue discussed is the "Norway problem," which arises from the language's historical implementation of implicit boolean typing, where string literals resembling boolean values, such as "no," are parsed incorrectly as the boolean value false. This behavior causes parsing ambiguity, as the literal string "no" can be interpreted as the boolean false, conflicting with developer expectations that strings should remain distinct from boolean types. A workaround for this behavior involves explicitly quoting the values, such as quoting the country code to force it to be treated as a string, thereby allowing correct parsing.

The persistence of this issue is rooted in the evolution of the YAML specification. In the initial specification of May 2001, YAML allowed for implicit typing, supporting English words like true, false, yes, no, and on, off, which enabled this ambiguity. This implicit typing was maintained through YAML versions 1.0 and 1.1, which included support for these boolean representations. The problem was formally addressed in the July 2009 revision, YAML v1.2.0, which sought to align YAML with JSON by removing implicit typing rules and defining booleans explicitly as true, false, yes, no, etc., treating them primarily as strings. Consequently, the official specification suggests that the issue was theoretically resolved by removing implicit boolean typing.

However, the practical manifestation of the Norway problem persists because the implementation across various libraries has lagged in adopting the v1.2 specification. Despite the specification changes, many widely used YAML libraries, including PyYaml and LibYaml, have not fully transitioned to supporting v1.2 features, meaning they retain the implicit typing behavior from the older specification. This results in a fragmented ecosystem where the theoretical fix in the specification does not universally translate into corrected library behavior.

Understanding this persistence requires acknowledging the complexity of YAML itself. The language integrates numerous concepts from other standards and possesses intricate rules regarding string quoting, whitespace, and data types. This complexity, coupled with the slow pace of adoption for specification changes, means that subtle quirks can cascade into unexpected issues when implementing parsers. While some projects, such as ruamel.yaml and gopkg.in/yaml.v3, have adopted v1.2 behavior, legacy implementations remain popular, highlighting a tension between specification correctness and backward compatibility in the software ecosystem.

Ultimately, the Norway problem is less a bug in the current specification and more a consequence of historical implementation choices and the slow, incremental nature of large-scale ecosystem updates. While implicit boolean typing has been removed from the official specification, the continued support for older specifications by popular libraries means that users must still account for potential type coercion depending on the specific parser in use. Moving forward, the trend indicates a move towards stricter adherence to the v1.2 model, suggesting that new projects adopting newer libraries are less likely to encounter this particular type of ambiguity.