diff --git a/include/nlohmann/detail/json_pointer.hpp b/include/nlohmann/detail/json_pointer.hpp
index 18b66e23..56280292 100644
--- a/include/nlohmann/detail/json_pointer.hpp
+++ b/include/nlohmann/detail/json_pointer.hpp
@@ -3,6 +3,7 @@
 #include <algorithm> // all_of
 #include <cassert> // assert
 #include <cctype> // isdigit
+#include <limits> // max
 #include <numeric> // accumulate
 #include <string> // string
 #include <utility> // move
@@ -328,9 +329,12 @@ class json_pointer
     @throw parse_error.106  if an array index begins with '0'
     @throw parse_error.109  if an array index begins not with a digit
     @throw out_of_range.404 if string @a s could not be converted to an integer
+    @throw out_of_range.410 if an array index exceeds size_type
     */
-    static int array_index(const std::string& s)
+    static typename BasicJsonType::size_type array_index(const std::string& s)
     {
+        using size_type = typename BasicJsonType::size_type;
+
         // error condition (cf. RFC 6901, Sect. 4)
         if (JSON_HEDLEY_UNLIKELY(s.size() > 1 and s[0] == '0'))
         {
@@ -346,10 +350,10 @@ class json_pointer
         }
 
         std::size_t processed_chars = 0;
-        int res = 0;
+        unsigned long long res = 0;
         JSON_TRY
         {
-            res = std::stoi(s, &processed_chars);
+            res = std::stoull(s, &processed_chars);
         }
         JSON_CATCH(std::out_of_range&)
         {
@@ -362,7 +366,14 @@ class json_pointer
             JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
         }
 
-        return res;
+        // only triggered on special platforms (like 32bit), see also
+        // https://github.com/nlohmann/json/pull/2203
+        if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)()))
+        {
+            JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type")); // LCOV_EXCL_LINE
+        }
+
+        return static_cast<size_type>(res);
     }
 
     json_pointer top() const
@@ -421,7 +432,7 @@ class json_pointer
                 case detail::value_t::array:
                 {
                     // create an entry in the array
-                    result = &result->operator[](static_cast<size_type>(array_index(reference_token)));
+                    result = &result->operator[](array_index(reference_token));
                     break;
                 }
 
@@ -499,8 +510,7 @@ class json_pointer
                     else
                     {
                         // convert array index to number; unchecked access
-                        ptr = &ptr->operator[](
-                                  static_cast<size_type>(array_index(reference_token)));
+                        ptr = &ptr->operator[](array_index(reference_token));
                     }
                     break;
                 }
@@ -544,7 +554,7 @@ class json_pointer
                     }
 
                     // note: at performs range check
-                    ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
+                    ptr = &ptr->at(array_index(reference_token));
                     break;
                 }
 
@@ -594,8 +604,7 @@ class json_pointer
                     }
 
                     // use unchecked array access
-                    ptr = &ptr->operator[](
-                              static_cast<size_type>(array_index(reference_token)));
+                    ptr = &ptr->operator[](array_index(reference_token));
                     break;
                 }
 
@@ -638,7 +647,7 @@ class json_pointer
                     }
 
                     // note: at performs range check
-                    ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
+                    ptr = &ptr->at(array_index(reference_token));
                     break;
                 }
 
@@ -702,7 +711,7 @@ class json_pointer
                         }
                     }
 
-                    const auto idx = static_cast<size_type>(array_index(reference_token));
+                    const auto idx = array_index(reference_token);
                     if (idx >= ptr->size())
                     {
                         // index out of range
diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp
index 790ecd4b..048307b3 100644
--- a/include/nlohmann/json.hpp
+++ b/include/nlohmann/json.hpp
@@ -8179,7 +8179,7 @@ class basic_json
                     else
                     {
                         const auto idx = json_pointer::array_index(last_path);
-                        if (JSON_HEDLEY_UNLIKELY(static_cast<size_type>(idx) > parent.size()))
+                        if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
                         {
                             // avoid undefined behavior
                             JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
@@ -8222,7 +8222,7 @@ class basic_json
             else if (parent.is_array())
             {
                 // note erase performs range check
-                parent.erase(static_cast<size_type>(json_pointer::array_index(last_path)));
+                parent.erase(json_pointer::array_index(last_path));
             }
         };
 
diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp
index 22fc0e33..b919d231 100644
--- a/single_include/nlohmann/json.hpp
+++ b/single_include/nlohmann/json.hpp
@@ -11032,6 +11032,7 @@ class json_reverse_iterator : public std::reverse_iterator<Base>
 #include <algorithm> // all_of
 #include <cassert> // assert
 #include <cctype> // isdigit
+#include <limits> // max
 #include <numeric> // accumulate
 #include <string> // string
 #include <utility> // move
@@ -11360,9 +11361,12 @@ class json_pointer
     @throw parse_error.106  if an array index begins with '0'
     @throw parse_error.109  if an array index begins not with a digit
     @throw out_of_range.404 if string @a s could not be converted to an integer
+    @throw out_of_range.410 if an array index exceeds size_type
     */
-    static int array_index(const std::string& s)
+    static typename BasicJsonType::size_type array_index(const std::string& s)
     {
+        using size_type = typename BasicJsonType::size_type;
+
         // error condition (cf. RFC 6901, Sect. 4)
         if (JSON_HEDLEY_UNLIKELY(s.size() > 1 and s[0] == '0'))
         {
@@ -11378,10 +11382,10 @@ class json_pointer
         }
 
         std::size_t processed_chars = 0;
-        int res = 0;
+        unsigned long long res = 0;
         JSON_TRY
         {
-            res = std::stoi(s, &processed_chars);
+            res = std::stoull(s, &processed_chars);
         }
         JSON_CATCH(std::out_of_range&)
         {
@@ -11394,7 +11398,14 @@ class json_pointer
             JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
         }
 
-        return res;
+        // only triggered on special platforms (like 32bit), see also
+        // https://github.com/nlohmann/json/pull/2203
+        if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)()))
+        {
+            JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type")); // LCOV_EXCL_LINE
+        }
+
+        return static_cast<size_type>(res);
     }
 
     json_pointer top() const
@@ -11453,7 +11464,7 @@ class json_pointer
                 case detail::value_t::array:
                 {
                     // create an entry in the array
-                    result = &result->operator[](static_cast<size_type>(array_index(reference_token)));
+                    result = &result->operator[](array_index(reference_token));
                     break;
                 }
 
@@ -11531,8 +11542,7 @@ class json_pointer
                     else
                     {
                         // convert array index to number; unchecked access
-                        ptr = &ptr->operator[](
-                                  static_cast<size_type>(array_index(reference_token)));
+                        ptr = &ptr->operator[](array_index(reference_token));
                     }
                     break;
                 }
@@ -11576,7 +11586,7 @@ class json_pointer
                     }
 
                     // note: at performs range check
-                    ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
+                    ptr = &ptr->at(array_index(reference_token));
                     break;
                 }
 
@@ -11626,8 +11636,7 @@ class json_pointer
                     }
 
                     // use unchecked array access
-                    ptr = &ptr->operator[](
-                              static_cast<size_type>(array_index(reference_token)));
+                    ptr = &ptr->operator[](array_index(reference_token));
                     break;
                 }
 
@@ -11670,7 +11679,7 @@ class json_pointer
                     }
 
                     // note: at performs range check
-                    ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
+                    ptr = &ptr->at(array_index(reference_token));
                     break;
                 }
 
@@ -11734,7 +11743,7 @@ class json_pointer
                         }
                     }
 
-                    const auto idx = static_cast<size_type>(array_index(reference_token));
+                    const auto idx = array_index(reference_token);
                     if (idx >= ptr->size())
                     {
                         // index out of range
@@ -23971,7 +23980,7 @@ class basic_json
                     else
                     {
                         const auto idx = json_pointer::array_index(last_path);
-                        if (JSON_HEDLEY_UNLIKELY(static_cast<size_type>(idx) > parent.size()))
+                        if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
                         {
                             // avoid undefined behavior
                             JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
@@ -24014,7 +24023,7 @@ class basic_json
             else if (parent.is_array())
             {
                 // note erase performs range check
-                parent.erase(static_cast<size_type>(json_pointer::array_index(last_path)));
+                parent.erase(json_pointer::array_index(last_path));
             }
         };
 
diff --git a/test/src/unit-json_pointer.cpp b/test/src/unit-json_pointer.cpp
index ca11efa4..89a41d76 100644
--- a/test/src/unit-json_pointer.cpp
+++ b/test/src/unit-json_pointer.cpp
@@ -348,12 +348,29 @@ TEST_CASE("JSON pointers")
             CHECK_THROWS_WITH(j_const["/1+1"_json_pointer] == 1,
                               "[json.exception.out_of_range.404] unresolved reference token '1+1'");
 
-            CHECK_THROWS_AS(j["/111111111111111111111111"_json_pointer] = 1, json::out_of_range&);
-            CHECK_THROWS_WITH(j["/111111111111111111111111"_json_pointer] = 1,
-                              "[json.exception.out_of_range.404] unresolved reference token '111111111111111111111111'");
-            CHECK_THROWS_AS(j_const["/111111111111111111111111"_json_pointer] == 1, json::out_of_range&);
-            CHECK_THROWS_WITH(j_const["/111111111111111111111111"_json_pointer] == 1,
-                              "[json.exception.out_of_range.404] unresolved reference token '111111111111111111111111'");
+            {
+                auto too_large_index = std::to_string((std::numeric_limits<unsigned long long>::max)()) + "1";
+                json::json_pointer jp(std::string("/") + too_large_index);
+                std::string throw_msg = std::string("[json.exception.out_of_range.404] unresolved reference token '") + too_large_index + "'";
+
+                CHECK_THROWS_AS(j[jp] = 1, json::out_of_range&);
+                CHECK_THROWS_WITH(j[jp] = 1, throw_msg.c_str());
+                CHECK_THROWS_AS(j_const[jp] == 1, json::out_of_range&);
+                CHECK_THROWS_WITH(j_const[jp] == 1, throw_msg.c_str());
+            }
+
+            if (sizeof(typename json::size_type) < sizeof(unsigned long long))
+            {
+                auto size_type_max_uul = static_cast<unsigned long long>((std::numeric_limits<json::size_type>::max)());
+                auto too_large_index = std::to_string(size_type_max_uul);
+                json::json_pointer jp(std::string("/") + too_large_index);
+                std::string throw_msg = std::string("[json.exception.out_of_range.410] array index ") + too_large_index + " exceeds size_type";
+
+                CHECK_THROWS_AS(j[jp] = 1, json::out_of_range&);
+                CHECK_THROWS_WITH(j[jp] = 1, throw_msg.c_str());
+                CHECK_THROWS_AS(j_const[jp] == 1, json::out_of_range&);
+                CHECK_THROWS_WITH(j_const[jp] == 1, throw_msg.c_str());
+            }
 
             CHECK_THROWS_AS(j.at("/one"_json_pointer) = 1, json::parse_error&);
             CHECK_THROWS_WITH(j.at("/one"_json_pointer) = 1,