diff --git a/README.md b/README.md
index d39663ee..2dd60bf1 100644
--- a/README.md
+++ b/README.md
@@ -428,7 +428,7 @@ $ make
 $ ./json_unit "*"
 
 ===============================================================================
-All tests passed (3344299 assertions in 29 test cases)
+All tests passed (3344416 assertions in 30 test cases)
 ```
 
 For more information, have a look at the file [.travis.yml](https://github.com/nlohmann/json/blob/master/.travis.yml).
diff --git a/doc/examples/flatten.cpp b/doc/examples/flatten.cpp
index 5d769202..0601f8a3 100644
--- a/doc/examples/flatten.cpp
+++ b/doc/examples/flatten.cpp
@@ -31,4 +31,7 @@ int main()
 
     // call flatten()
     std::cout << std::setw(4) << j.flatten() << '\n';
+
+    // flatten for a primitive value
+    std::cout << j["pi"].flatten() << '\n';
 }
diff --git a/doc/examples/flatten.link b/doc/examples/flatten.link
index 70ba78ba..0fe78bbb 100644
--- a/doc/examples/flatten.link
+++ b/doc/examples/flatten.link
@@ -1 +1 @@
-<a target="_blank" href="http://melpon.org/wandbox/permlink/kODXfzcksgstdBRD"><b>online</b></a>
\ No newline at end of file
+<a target="_blank" href="http://melpon.org/wandbox/permlink/skGi8b32VhI8HOgV"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/flatten.output b/doc/examples/flatten.output
index beb368fa..fedfc8ef 100644
--- a/doc/examples/flatten.output
+++ b/doc/examples/flatten.output
@@ -14,3 +14,4 @@
     "/object/~1": "slash",
     "/pi": 3.141
 }
+{"":3.141}
diff --git a/src/json.hpp b/src/json.hpp
index 47046c03..030c8f2c 100644
--- a/src/json.hpp
+++ b/src/json.hpp
@@ -3273,8 +3273,8 @@ class basic_json
 
     @return reference to the element at index @a idx
 
-    @throw std::domain_error if JSON is not an array or null; example: `"cannot
-    use operator[] with string"`
+    @throw std::domain_error if JSON is not an array or null; example:
+    `"cannot use operator[] with string"`
 
     @complexity Constant if @a idx is in the range of the array. Otherwise
     linear in `idx - size()`.
@@ -3620,7 +3620,9 @@ class basic_json
 
     @complexity Linear in the length of the JSON pointer.
 
-    @throw std::out_of_range  if the JSON pointer can not be resolved
+    @throw std::out_of_range      if the JSON pointer can not be resolved
+    @throw std::domain_error      if an array index begins with '0'
+    @throw std::invalid_argument  if an array index was not a number
 
     @liveexample{The behavior is shown in the example.,operatorjson_pointer}
 
@@ -3645,8 +3647,9 @@ class basic_json
 
     @complexity Linear in the length of the JSON pointer.
 
-    @throw std::out_of_range  if the JSON pointer can not be resolved
-    @throw std::out_of_range  if the special value `-` is used for an array
+    @throw std::out_of_range      if the JSON pointer can not be resolved
+    @throw std::domain_error      if an array index begins with '0'
+    @throw std::invalid_argument  if an array index was not a number
 
     @liveexample{The behavior is shown in the example.,
     operatorjson_pointer_const}
@@ -8923,9 +8926,12 @@ basic_json_parser_63:
                       empty string is assumed which references the whole JSON
                       value
 
-        @throw std::domain_error  if reference token is nonempty and does not
-               begin with a slash (`/`), or if a tilde (`~`) is not followed
-               by `0` (representing `~`) or `1` (representing `/`).
+        @throw std::domain_error if reference token is nonempty and does not
+        begin with a slash (`/`); example: `"JSON pointer must be empty or
+        begin with /"`
+        @throw std::domain_error if a tilde (`~`) is not followed by `0`
+        (representing `~`) or `1` (representing `/`); example: `"escape error:
+        ~ must be followed with 0 or 1"`
 
         @liveexample{The example shows the construction several valid JSON
         pointers as well as the exceptional behavior.,json_pointer}
@@ -8944,6 +8950,8 @@ basic_json_parser_63:
         {
             pointer result = &j;
 
+            // in case no reference tokens exist, return a reference to the
+            // JSON value j which will be overwritten by a primitive value
             for (const auto& reference_token : reference_tokens)
             {
                 switch (result->m_type)
@@ -8952,10 +8960,12 @@ basic_json_parser_63:
                     {
                         if (reference_token == "0")
                         {
+                            // start a new array if reference token is 0
                             result = &result->operator[](0);
                         }
                         else
                         {
+                            // start a new object otherwise
                             result = &result->operator[](reference_token);
                         }
                         break;
@@ -8963,19 +8973,38 @@ basic_json_parser_63:
 
                     case value_t::object:
                     {
+                        // create an entry in the object
                         result = &result->operator[](reference_token);
                         break;
                     }
 
                     case value_t::array:
                     {
+                        // create an entry in the array
                         result = &result->operator[](static_cast<size_t>(std::stoi(reference_token)));
                         break;
                     }
 
+                    /*
+                    This function is only to be called from the unflatten()
+                    function. There, j is initially of type null.
+
+                    - In case the reference tokens are empty, a reference to
+                      j is returned and overwritten by the desired value by
+                      the unflatten() function.
+                    - If there are reference tokens, the null value of j will
+                      be changed to an object or array after reading the first
+                      reference token.
+                    - All subsequent tokens work on arrays or objects and will
+                      not change the type of j.
+
+                    Consequently, the type of @a j will always be null,
+                    object, or array. Hence, the following line is
+                    unreachable.
+                    */
                     default:
                     {
-                        throw std::domain_error("unresolved reference token '" + reference_token + "'");
+                        break; // LCOV_EXCL_LINE
                     }
                 }
             }
@@ -9361,7 +9390,11 @@ basic_json_parser_63:
                     throw std::domain_error("values in object must be primitive");
                 }
 
-                // assign value to reference pointed to by JSON pointer
+                // assign value to reference pointed to by JSON pointer;
+                // Note that if the JSON pointer is "" (i.e., points to the
+                // whole value), function get_and_create returns a reference
+                // to result itself. An assignment will then create a
+                // primitive value.
                 json_pointer(element.first).get_and_create(result) = element.second;
             }
 
@@ -9390,7 +9423,8 @@ basic_json_parser_63:
 
     @return an object that maps JSON pointers to primitve values
 
-    @note Empty objects and arrays are flattened to `null`.
+    @note Empty objects and arrays are flattened to `null` and will not be
+          reconstructed correctly by the @ref unflatten() function.
 
     @complexity Linear in the size the JSON value.
 
@@ -9428,6 +9462,8 @@ basic_json_parser_63:
 
     @complexity Linear in the size the JSON value.
 
+    @throws std::domain_error
+
     @liveexample{The following code shows how a flattened JSON object is
     unflattened into the original nested JSON object.,unflatten}
 
diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c
index ac11f08a..f5fbe65b 100644
--- a/src/json.hpp.re2c
+++ b/src/json.hpp.re2c
@@ -3273,8 +3273,8 @@ class basic_json
 
     @return reference to the element at index @a idx
 
-    @throw std::domain_error if JSON is not an array or null; example: `"cannot
-    use operator[] with string"`
+    @throw std::domain_error if JSON is not an array or null; example:
+    `"cannot use operator[] with string"`
 
     @complexity Constant if @a idx is in the range of the array. Otherwise
     linear in `idx - size()`.
@@ -3620,7 +3620,9 @@ class basic_json
 
     @complexity Linear in the length of the JSON pointer.
 
-    @throw std::out_of_range  if the JSON pointer can not be resolved
+    @throw std::out_of_range      if the JSON pointer can not be resolved
+    @throw std::domain_error      if an array index begins with '0'
+    @throw std::invalid_argument  if an array index was not a number
 
     @liveexample{The behavior is shown in the example.,operatorjson_pointer}
 
@@ -3645,8 +3647,9 @@ class basic_json
 
     @complexity Linear in the length of the JSON pointer.
 
-    @throw std::out_of_range  if the JSON pointer can not be resolved
-    @throw std::out_of_range  if the special value `-` is used for an array
+    @throw std::out_of_range      if the JSON pointer can not be resolved
+    @throw std::domain_error      if an array index begins with '0'
+    @throw std::invalid_argument  if an array index was not a number
 
     @liveexample{The behavior is shown in the example.,
     operatorjson_pointer_const}
@@ -8233,9 +8236,12 @@ class basic_json
                       empty string is assumed which references the whole JSON
                       value
 
-        @throw std::domain_error  if reference token is nonempty and does not
-               begin with a slash (`/`), or if a tilde (`~`) is not followed
-               by `0` (representing `~`) or `1` (representing `/`).
+        @throw std::domain_error if reference token is nonempty and does not
+        begin with a slash (`/`); example: `"JSON pointer must be empty or
+        begin with /"`
+        @throw std::domain_error if a tilde (`~`) is not followed by `0`
+        (representing `~`) or `1` (representing `/`); example: `"escape error:
+        ~ must be followed with 0 or 1"`
 
         @liveexample{The example shows the construction several valid JSON
         pointers as well as the exceptional behavior.,json_pointer}
@@ -8254,6 +8260,8 @@ class basic_json
         {
             pointer result = &j;
 
+            // in case no reference tokens exist, return a reference to the
+            // JSON value j which will be overwritten by a primitive value
             for (const auto& reference_token : reference_tokens)
             {
                 switch (result->m_type)
@@ -8262,10 +8270,12 @@ class basic_json
                     {
                         if (reference_token == "0")
                         {
+                            // start a new array if reference token is 0
                             result = &result->operator[](0);
                         }
                         else
                         {
+                            // start a new object otherwise
                             result = &result->operator[](reference_token);
                         }
                         break;
@@ -8273,19 +8283,38 @@ class basic_json
 
                     case value_t::object:
                     {
+                        // create an entry in the object
                         result = &result->operator[](reference_token);
                         break;
                     }
 
                     case value_t::array:
                     {
+                        // create an entry in the array
                         result = &result->operator[](static_cast<size_t>(std::stoi(reference_token)));
                         break;
                     }
 
+                    /*
+                    This function is only to be called from the unflatten()
+                    function. There, j is initially of type null.
+
+                    - In case the reference tokens are empty, a reference to
+                      j is returned and overwritten by the desired value by
+                      the unflatten() function.
+                    - If there are reference tokens, the null value of j will
+                      be changed to an object or array after reading the first
+                      reference token.
+                    - All subsequent tokens work on arrays or objects and will
+                      not change the type of j.
+
+                    Consequently, the type of @a j will always be null,
+                    object, or array. Hence, the following line is
+                    unreachable.
+                    */
                     default:
                     {
-                        throw std::domain_error("unresolved reference token '" + reference_token + "'");
+                        break; // LCOV_EXCL_LINE
                     }
                 }
             }
@@ -8671,7 +8700,11 @@ class basic_json
                     throw std::domain_error("values in object must be primitive");
                 }
 
-                // assign value to reference pointed to by JSON pointer
+                // assign value to reference pointed to by JSON pointer;
+                // Note that if the JSON pointer is "" (i.e., points to the
+                // whole value), function get_and_create returns a reference
+                // to result itself. An assignment will then create a
+                // primitive value.
                 json_pointer(element.first).get_and_create(result) = element.second;
             }
 
@@ -8700,7 +8733,8 @@ class basic_json
 
     @return an object that maps JSON pointers to primitve values
 
-    @note Empty objects and arrays are flattened to `null`.
+    @note Empty objects and arrays are flattened to `null` and will not be
+          reconstructed correctly by the @ref unflatten() function.
 
     @complexity Linear in the size the JSON value.
 
@@ -8738,6 +8772,8 @@ class basic_json
 
     @complexity Linear in the size the JSON value.
 
+    @throws std::domain_error
+
     @liveexample{The following code shows how a flattened JSON object is
     unflattened into the original nested JSON object.,unflatten}
 
diff --git a/test/unit.cpp b/test/unit.cpp
index f79a29fd..f5a6fc09 100644
--- a/test/unit.cpp
+++ b/test/unit.cpp
@@ -12365,6 +12365,11 @@ TEST_CASE("JSON pointers")
         CHECK_THROWS_AS(json({{"/1", {1, 2, 3}}}).unflatten(), std::domain_error);
         CHECK_THROWS_WITH(json({{"/1", {1, 2, 3}}}).unflatten(), "values in object must be primitive");
 
+        // error for conflicting values
+        json j_error = {{"", 42}, {"/foo", 17}};
+        CHECK_THROWS_AS(j_error.unflatten(), std::domain_error);
+        CHECK_THROWS_WITH(j_error.unflatten(), "unresolved reference token 'foo'");
+
         // explicit roundtrip check
         CHECK(j.flatten().unflatten() == j);