diff --git a/src/base/io/json/Json.cpp b/src/base/io/json/Json.cpp
index cd7213d22..48016665a 100644
--- a/src/base/io/json/Json.cpp
+++ b/src/base/io/json/Json.cpp
@@ -191,6 +191,37 @@ rapidjson::Value xmrig::Json::normalize(double value, bool zero)
 }
 
 
+bool xmrig::Json::convertOffset(std::ifstream& ifs, size_t offset, size_t& line, size_t& pos, std::vector<std::string>& s)
+{
+    std::string prev_t;
+    std::string t;
+    line = 0;
+    pos = 0;
+    size_t k = 0;
+
+    while (!ifs.eof()) {
+        prev_t = t;
+        std::getline(ifs, t);
+        k += t.length() + 1;
+        ++line;
+
+        if (k > offset) {
+            pos = offset + t.length() + 1 - k + 1;
+
+            s.clear();
+            if (!prev_t.empty()) {
+                s.emplace_back(prev_t);
+            }
+            s.emplace_back(t);
+
+            return true;
+        }
+    }
+
+    return false;
+}
+
+
 bool xmrig::JsonReader::isEmpty() const
 {
     return Json::isEmpty(m_obj);
diff --git a/src/base/io/json/Json.h b/src/base/io/json/Json.h
index 15f340a76..7ceae5dd3 100644
--- a/src/base/io/json/Json.h
+++ b/src/base/io/json/Json.h
@@ -28,6 +28,9 @@
 
 #include "base/kernel/interfaces/IJsonReader.h"
 #include "rapidjson/fwd.h"
+#include <string>
+#include <vector>
+#include <fstream>
 
 
 namespace xmrig {
@@ -50,7 +53,12 @@ public:
     static bool get(const char *fileName, rapidjson::Document &doc);
     static bool save(const char *fileName, const rapidjson::Document &doc);
 
+    static bool convertOffset(const char *fileName, size_t offset, size_t &line, size_t &pos, std::vector<std::string>& s);
+
     static rapidjson::Value normalize(double value, bool zero);
+
+private:
+    static bool convertOffset(std::ifstream& ifs, size_t offset, size_t& line, size_t& pos, std::vector<std::string>& s);
 };
 
 
diff --git a/src/base/io/json/JsonChain.cpp b/src/base/io/json/JsonChain.cpp
index bbaabbde9..48f04be7d 100644
--- a/src/base/io/json/JsonChain.cpp
+++ b/src/base/io/json/JsonChain.cpp
@@ -64,7 +64,27 @@ bool xmrig::JsonChain::addFile(const char *fileName)
     }
 
     if (doc.HasParseError()) {
-        LOG_ERR("%s<offset:%zu>: \"%s\"", fileName, doc.GetErrorOffset(), GetParseError_En(doc.GetParseError()));
+        const size_t offset = doc.GetErrorOffset();
+
+        size_t line, pos;
+        std::vector<std::string> s;
+        if (Json::convertOffset(fileName, offset, line, pos, s)) {
+            for (const auto& t : s) {
+                LOG_ERR("%s", t.c_str());
+            }
+
+            std::string t;
+            if (pos > 0) {
+                t.assign(pos - 1, ' ');
+            }
+            t += '^';
+            LOG_ERR("%s", t.c_str());
+
+            LOG_ERR("%s<line:%zu, position:%zu>: \"%s\"", fileName, line, pos, GetParseError_En(doc.GetParseError()));
+        }
+        else {
+            LOG_ERR("%s<offset:%zu>: \"%s\"", fileName, offset, GetParseError_En(doc.GetParseError()));
+        }
     }
     else {
         LOG_ERR("unable to open \"%s\".", fileName);
diff --git a/src/base/io/json/Json_unix.cpp b/src/base/io/json/Json_unix.cpp
index dedea947d..f31e1bd0c 100644
--- a/src/base/io/json/Json_unix.cpp
+++ b/src/base/io/json/Json_unix.cpp
@@ -62,3 +62,14 @@ bool xmrig::Json::save(const char *fileName, const rapidjson::Document &doc)
 
     return true;
 }
+
+
+bool xmrig::Json::convertOffset(const char* fileName, size_t offset, size_t& line, size_t& pos, std::vector<std::string>& s)
+{
+    std::ifstream ifs(fileName, std::ios_base::in | std::ios_base::binary);
+    if (!ifs.is_open()) {
+        return false;
+    }
+
+    return convertOffset(ifs, offset, line, pos, s);
+}
diff --git a/src/base/io/json/Json_win.cpp b/src/base/io/json/Json_win.cpp
index cb6f02f64..693594832 100644
--- a/src/base/io/json/Json_win.cpp
+++ b/src/base/io/json/Json_win.cpp
@@ -125,3 +125,31 @@ bool xmrig::Json::save(const char *fileName, const rapidjson::Document &doc)
 
     return true;
 }
+
+
+bool xmrig::Json::convertOffset(const char* fileName, size_t offset, size_t& line, size_t& pos, std::vector<std::string>& s)
+{
+    constexpr const std::ios_base::openmode mode = std::ios_base::in | std::ios_base::binary;
+
+#   if defined(_MSC_VER)
+    std::ifstream ifs(toUtf16(fileName), mode);
+    if (!ifs.is_open()) {
+        return false;
+    }
+#   elif defined(__GNUC__)
+    const int fd = _wopen(toUtf16(fileName).c_str(), _O_RDONLY | _O_BINARY);
+    if (fd == -1) {
+        return false;
+    }
+
+    __gnu_cxx::stdio_filebuf<char> buf(fd, mode);
+    std::istream ifs(&buf);
+#   else
+    std::ifstream ifs(fileName, mode);
+    if (!ifs.is_open()) {
+        return false;
+    }
+#   endif
+
+    return convertOffset(ifs, offset, line, pos, s);
+}