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