{"slug": "yaml-that-s-norway-problem", "title": "YAML? That's Norway Problem", "summary": "The article explains the \"Norway problem\" in YAML, where the country code \"NO\" is incorrectly parsed as the boolean value `false` because YAML treats certain English words like \"no\" as booleans for human readability. This issue occurs despite \"NO\" being intended as a country code in a list, and the article demonstrates how quoting the value as `\"NO\"` resolves the problem. The feature originated from YAML's optional boolean type specification, which allowed words like \"yes,\" \"no,\" \"on,\" and \"off\" to be interpreted as booleans.", "body_md": "2026-01-12\n\nYaml 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:\n\n```\n# project.yaml\n\ntitle: Nonoverse\ndescription: Beautiful puzzle game about nonograms.\nlink: https://lab174.com/nonoverse\ncountries:\n  - DE\n  - FR\n  - PL\n  - RO\n```\n\nLet’s verify that the above example parses correctly.\n\nWe’ll use Python[ 1](#fn1) with PyYaml\n\n```\npython3 -m pip install pyyaml==6.0.3\n```\n\nNow let’s write a simple script to parse the yaml file:\n\n``` python\n# python-pyyaml.py\n\nimport json\nimport yaml\n\nwith open(\"project.yaml\", \"r\", encoding=\"utf-8\") as f:\n    data = yaml.safe_load(f)\n\nprint(json.dumps(data, indent=2))\n```\n\nRunning `python3 python-pyyaml.py`\n\nproduces this\noutput:\n\n```\n{\n  \"title\": \"Nonoverse\",\n  \"description\": \"Beautiful puzzle game about nonograms.\",\n  \"link\": \"https://lab174.com/nonoverse\",\n  \"countries\": [\n    \"DE\",\n    \"FR\",\n    \"PL\",\n    \"RO\"\n  ]\n}\n```\n\nSo far everything behaves as expected.\n\nWhen we change the original yaml file and add Norway’s two letter iso country code to the existing list:\n\n```\ncountries:\n  - DE\n  - FR\n  - NO\n  - PL\n  - RO\n```\n\nUsing the same parsing method, the file now yields this result:\n\n```\n{\n  \"title\": \"Nonoverse\",\n  \"description\": \"Beautiful puzzle game about nonograms.\",\n  \"link\": \"https://lab174.com/nonoverse\",\n  \"countries\": [\n    \"DE\",\n    \"FR\",\n    false,\n    \"PL\",\n    \"RO\"\n  ]\n}\n```\n\nNote that `NO`\n\nhas been replaced with `false`\n\n.\nThis is unexpected. Nothing about the context suggests a boolean should\nappear here. The `NO`\n\nliteral sits in a list of country codes\nlike `FR`\n\nor `PL`\n\nand appears similar in form. The\nproblem, of course, is that “no” is also an English word with a negative\nmeaning.\n\nThis feature was originally added to allow writing booleans in a more human readable way, e.g.:\n\n```\nplatforms:\n  iPhone: yes\n  iPad: yes\n  AppleWatch: no\n```\n\nThis gets parsed as:\n\n```\n{\n  \"platforms\": {\n    \"iPhone\": true,\n    \"iPad\": true,\n    \"AppleWatch\": false\n  }\n}\n```\n\nThe idea was that configuration files should read like natural language. In practice this behavior proved problematic, becoming the notorious Norway problem in yaml.\n\nOne workaround is to escape the string, like this:\n\n```\ncountries:\n  - DE\n  - FR\n  - \"NO\"\n  - PL\n  - RO\n```\n\nWith quotes, the file parses as expected:\n\n```\n{\n  \"title\": \"Nonoverse\",\n  \"description\": \"Beautiful puzzle game about nonograms.\",\n  \"link\": \"https://lab174.com/nonoverse\",\n  \"platforms\": {\n    \"iPhone\": true,\n    \"iPad\": true,\n    \"AppleWatch\": false\n  },\n  \"countries\": [\n    \"DE\",\n    \"FR\",\n    \"NO\",\n    \"PL\",\n    \"RO\"\n  ]\n}\n```\n\nMany articles about yaml’s Norway problem stop here, presenting quoting as the canonical fix. There is more.\n\nTo understand today’s state of the Norway problem we’ll first look at how yaml evolved.\n\nAt 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.\n\n```\nbuyer    : %\n    address     : %\n       city       : Royal Oak\n       line one   : 458 Wittigen's Way\n       line two   : Suite 292\n       postal     : 48046\n       state      : MI\n    family name : Dumars\n    given name  : Chris\n```\n\nThe document makes no mention of parsing `no`\n\nto\n`false`\n\n. The “Serilization Format / bnf” section even contains a typo and a “to do”\nnote[ 3](#fn3):\n\nThis section contains the bnf\n\n[productions for the yaml syntax. Much to do…]4\n\nThis version describes various ways of presenting scalars[ 5](#fn5), including both quoted scalars and\nplain scalars with implicit typing. This is what we’re after.\n\nVersion 1.0 defined only `sequence`\n\n, `map`\n\n, and\n`string`\n\nas mandatory types[ 6](#fn6).\nThe rest were optional, but a reference specification existed. That\nreference specification for the optional boolean type included English\nword format. Supported words were:\n\n`true/false`\n\n,\n`on/off`\n\n, and also `yes/no`\n\nThis allows the Norway problem to appear – even if following that part of reference is described as optional.\n\n– Bonus: implicit typing can be overridden with explicit tags – we’ll talk about this later.\n\n– Bonus: single sign characters, i.e. `+`\n\nand\n`-`\n\nshould also be treated as `true`\n\nand\n`false`\n\n; even more so, as they are described as the canonical\nform[ 8](#fn8)!\n\nVersion 1.1 maintained the same implicit typing behavior as v1.0.\nHowever, the types listed in the spec – including boolean – while still\nnot mandatory, were now strongly recommended[ 9](#fn9).\n\n– Bonus: single sign characters are no longer included and the\ncanonical form is now `y/n`\n\n[ 10](#fn10).\n\nIts goal was to make yaml compliant\nwith json, going as far as allowing json to be a subset of yaml[ 11](#fn11).\n\n**Implicit typing rules have been removed, including the\nboolean English word format.**\n\n– Bonus: explicit typing rules are still present.\n\nOn paper, the Norway problem shouldn’t exist anymore, at least not since this yaml revision. So why are we still seeing it in 2026?\n\n| Yaml spec version | Date | Type of `no` : |\nValue of `no` |\n|---|---|---|---|\n| first pass specification | May 2001 | unspecified | unspecified |\n| v1.0 | January 2004 | boolean | `false` |\n| v1.1 | January 2005 | boolean | `false` |\n| v1.2.0 | July 2009 | string | `\"no\"` |\n\n`no`\n\n” and “Value of `no`\n\n”\nlabels refer to the literal without quotes.\nTo 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.\n\nWhat hides between the lines is that yaml and its specification are very, hugely,\n**extremely** complex. Seriously, it’s hard to overstate\nthis.\n\nSince v1.0 yaml’s goal was to build\nupon xml[ 12](#fn12)\nand a number of other technologies, as listed in the final draft\n\nYaml integrates and builds upon concepts described by C, Java, Perl, Python, Ruby, rfc0822 (mail), rfc1866 (html), rfc2045 (mime), rfc2396 (uri), xml, sax and soap\n\nYaml supports attachments, custom\ntags, references – the list goes on. There was even yaxml, an xml\nbinding for yaml[ 14](#fn14).\nThere are 9 ways of writing multiline strings – and some claim the\nnumber is actually 63\n\n`?`\n\n,\n`!`\n\n, `!!`\n\nin some cases have special meanings,\nwith 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.\n\nHow did libraries react to changes in such a complex specification?\n\nAs 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.\n\nBelow are some examples.\n\nAs mentioned before, PyYaml is Python’s most popular yaml library and one of the most popular Python libraries overall.\n\nPyYaml never added v1.2 support.\n\nThere is an open issue from 2017 in PyYaml’s Github project about introducing support\nfor v1.2[ 16](#fn16). There are at least two more\nrelated open issues, plus several closed ones. An unofficial library\n\nLibYaml 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.\n\nLibYaml also never added v1.2 support.\n\nAn open issue from 2016 in LibYaml’s\ngithub project requests adding v1.2 support[ 19](#fn19).\nAs mentioned earlier, LibYaml sits deep\nin dependency trees; changing its behavior is especially risky and slow.\nA less popular library, libfyaml\n\nCurrently unmaintained[ 21](#fn21), historically the most\npopular and still holds more Github stars then other Golang yaml libraries. It’s especially interesting\nbecause it declares support for a mix of v1.1 and 1.2\n\nKyaml is a yaml dialect built for the Kubernetes project,\nlaunched in June 2025. Its goal is to provide a safer and less ambiguous\ntool; it is also designed specifically for Kubernetes, trading\ngenerality for predictability. The announcement blog post references the\nNorway problem directly[ 24](#fn24).\n\nYaml’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.\n\nIn 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.\n\nMany texts don’t distinguish between yaml spec versions at all[ 25](#fn25).\nEven when spec version numbers are used, they’re frequently mistyped.\nIt’s not difficult to find documentation claiming that implicit boolean\ntyping is a trait of yaml specification\nversion 1.2\n\nOn the other hand we see users who declare the Norway problem as\nsolved because it doesn’t exist in the latest spec version, or because\nthey haven’t experienced it themselves, or for other reasons[ 28](#fn28). To be fair, that language feature\nwas removed over a decade ago, and it’s unexpected that popular\nlibraries still support the older spec version. Technically, the issue\nis solved in the spec – but in practice, most widely adopted\nimplementations still support implicit boolean typing, as we’ve\nseen.\n\nFinally, there are end users who are so unhappy with yaml that they prefer almost anything else[ 29](#fn29).\n\nWe 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.\n\nIn yaml final draft v1.0, the document\nspecified that, along with `yes`\n\nand `no`\n\n,\n`+`\n\nand `-`\n\nshould also be parsed as booleans.\nThis was removed v1.1. There was an idea to keep that functionality when\nplus or minus signs were preceded with a dot (`.+`\n\nand\n`.-`\n\n), but it didn’t catch on.\n\nDespite 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.\n\nThen 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.\n\nIf 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.\n\nA common reply is “no comments” – because json doesn’t support comments[ 30](#fn30);\nmany other yaml features aren’t supported\neither. This makes json a simpler and\nstricter alternative. Wheter that’s a better fit for your project, that\ndepends on the project. As always, personal preference plays a role too.\nNote: json has its own flavors, like\njsonc\n\nAfter writing this article, I’m still not entirely sure. Even though\nthe goal of yaml revision v1.2.0 was to\nmake that happen and revisions 1.2.0 and 1.2.1 claimed it explicitly[ 32](#fn32):\n\nYaml can therefore be viewed as a natural superset of json, offering improved human readability and a more complete information model.\n\nThat text has been removed from the latest yaml revision 1.2.2.\n\nA popular article[ 33](#fn33) claims to prove that yaml is not a superset of json, but that article uses a v1.1 parser – and\nas we know v1.1 never claimed json\ncompatibility. So that won’t help us.\n\nThe actual reason might be that yaml\nrequires maps to have unique keys[ 34](#fn34), while json only recommends it\n\nThis question is out of scope for this article – here the goal is to prioritize facts over “what if?”.\n\nIf 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.\n\nThese topics are only loosely related to the Norway problem, and this\ntext is already quite long. If you enjoyed reading it, leave positive\nfeedback somewhere and a Part 2 might happen. In the meantime, visit my\nhomepage[ 36](#fn36) and check out my other projects –\nmaybe you’ll find something else you’ll enjoy.\n\nImplicit 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:\n\n```\ntitle: Nonoverse\ndescription: Beautiful puzzle game about nonograms.\nlink: https://lab174.com/nonoverse\nplatforms:\n  iPhone: !!bool yes\n  iPad: !!bool yes\n  # Note the explicit typing here and above.\n  AppleWatch: !!bool no\ncountries:\n  - DE\n  - FR\n  - NO\n  - PL\n  - RO\n```\n\nWhen parsed with `yq`\n\n, a tool that supports yaml revision 1.2 by default:\n\n`yq eval -o=json project.yaml`\n\nIt returns:\n\n```\n{\n  \"title\": \"Nonoverse\",\n  \"description\": \"Beautiful puzzle game about nonograms.\",\n  \"link\": \"https://lab174.com/nonoverse\",\n  \"platforms\": {\n    \"iPhone\": true,\n    \"iPad\": true,\n    \"AppleWatch\": false\n  },\n  \"countries\": [\n    \"DE\",\n    \"FR\",\n    \"NO\",\n    \"PL\",\n    \"RO\"\n  ]\n}\n```\n\n", "url": "https://wpnews.pro/news/yaml-that-s-norway-problem", "canonical_source": "https://lab174.com/blog/202601-yaml-norway/", "published_at": "2026-05-21 04:18:53+00:00", "updated_at": "2026-05-23 00:04:41.755420+00:00", "lang": "en", "topics": ["developer-tools", "data"], "entities": ["PyYaml", "YAML", "Python", "Nonoverse"], "alternates": {"html": "https://wpnews.pro/news/yaml-that-s-norway-problem", "markdown": "https://wpnews.pro/news/yaml-that-s-norway-problem.md", "text": "https://wpnews.pro/news/yaml-that-s-norway-problem.txt", "jsonld": "https://wpnews.pro/news/yaml-that-s-norway-problem.jsonld"}}