diff --git a/components/detournavigator/asyncnavmeshupdater.cpp b/components/detournavigator/asyncnavmeshupdater.cpp
index 24d7cc0d32..71c8bbc2d3 100644
--- a/components/detournavigator/asyncnavmeshupdater.cpp
+++ b/components/detournavigator/asyncnavmeshupdater.cpp
@@ -10,6 +10,7 @@
 #include <components/debug/debuglog.hpp>
 #include <components/loadinglistener/loadinglistener.hpp>
 #include <components/misc/strings/conversion.hpp>
+#include <components/misc/strings/format.hpp>
 #include <components/misc/thread.hpp>
 
 #include <DetourNavMesh.h>
@@ -74,6 +75,36 @@ namespace DetourNavigator
         {
             return job.mGeneratedNavMeshData != nullptr;
         }
+
+        std::string makeRevision(const Version& version)
+        {
+            return Misc::StringUtils::format(".%zu.%zu", version.mGeneration, version.mRevision);
+        }
+
+        void writeDebugRecastMesh(
+            const Settings& settings, const TilePosition& tilePosition, const RecastMesh& recastMesh)
+        {
+            if (!settings.mEnableWriteRecastMeshToFile)
+                return;
+            std::string revision;
+            if (settings.mEnableRecastMeshFileNameRevision)
+                revision = makeRevision(recastMesh.getVersion());
+            writeToFile(recastMesh,
+                Misc::StringUtils::format(
+                    "%s%d.%d.", settings.mRecastMeshPathPrefix, tilePosition.x(), tilePosition.y()),
+                revision, settings.mRecast);
+        }
+
+        void writeDebugNavMesh(
+            const Settings& settings, const GuardedNavMeshCacheItem& navMeshCacheItem, const Version& version)
+        {
+            if (!settings.mEnableWriteNavMeshToFile)
+                return;
+            std::string revision;
+            if (settings.mEnableNavMeshFileNameRevision)
+                revision = makeRevision(version);
+            writeToFile(navMeshCacheItem.lockConst()->getImpl(), settings.mNavMeshPathPrefix, revision);
+        }
     }
 
     std::ostream& operator<<(std::ostream& stream, JobStatus value)
@@ -512,6 +543,8 @@ namespace DetourNavigator
             return JobStatus::Done;
         }
 
+        writeDebugRecastMesh(mSettings, job.mChangedTile, *recastMesh);
+
         NavMeshTilesCache::Value cachedNavMeshData
             = mNavMeshTilesCache.get(job.mAgentBounds, job.mChangedTile, *recastMesh);
         std::unique_ptr<PreparedNavMeshData> preparedNavMeshData;
@@ -633,7 +666,7 @@ namespace DetourNavigator
             mPresentTiles.insert(std::make_tuple(job.mAgentBounds, job.mChangedTile));
         }
 
-        writeDebugFiles(job, &recastMesh);
+        writeDebugNavMesh(mSettings, navMeshCacheItem, navMeshVersion);
 
         return isSuccess(status) ? JobStatus::Done : JobStatus::Fail;
     }
@@ -688,31 +721,6 @@ namespace DetourNavigator
         return job;
     }
 
-    void AsyncNavMeshUpdater::writeDebugFiles(const Job& job, const RecastMesh* recastMesh) const
-    {
-        std::string revision;
-        std::string recastMeshRevision;
-        std::string navMeshRevision;
-        if ((mSettings.get().mEnableWriteNavMeshToFile || mSettings.get().mEnableWriteRecastMeshToFile)
-            && (mSettings.get().mEnableRecastMeshFileNameRevision || mSettings.get().mEnableNavMeshFileNameRevision))
-        {
-            revision = "."
-                + std::to_string((std::chrono::steady_clock::now() - std::chrono::steady_clock::time_point()).count());
-            if (mSettings.get().mEnableRecastMeshFileNameRevision)
-                recastMeshRevision = revision;
-            if (mSettings.get().mEnableNavMeshFileNameRevision)
-                navMeshRevision = std::move(revision);
-        }
-        if (recastMesh && mSettings.get().mEnableWriteRecastMeshToFile)
-            writeToFile(*recastMesh,
-                mSettings.get().mRecastMeshPathPrefix + std::to_string(job.mChangedTile.x()) + "_"
-                    + std::to_string(job.mChangedTile.y()) + "_",
-                recastMeshRevision, mSettings.get().mRecast);
-        if (mSettings.get().mEnableWriteNavMeshToFile)
-            if (const auto shared = job.mNavMeshCacheItem.lock())
-                writeToFile(shared->lockConst()->getImpl(), mSettings.get().mNavMeshPathPrefix, navMeshRevision);
-    }
-
     bool AsyncNavMeshUpdater::lockTile(
         std::size_t jobId, const AgentBounds& agentBounds, const TilePosition& changedTile)
     {
diff --git a/components/detournavigator/asyncnavmeshupdater.hpp b/components/detournavigator/asyncnavmeshupdater.hpp
index a4c446afc9..7877ff8082 100644
--- a/components/detournavigator/asyncnavmeshupdater.hpp
+++ b/components/detournavigator/asyncnavmeshupdater.hpp
@@ -248,8 +248,6 @@ namespace DetourNavigator
 
         void postThreadJob(JobIt job, std::deque<JobIt>& queue);
 
-        void writeDebugFiles(const Job& job, const RecastMesh* recastMesh) const;
-
         bool lockTile(std::size_t jobId, const AgentBounds& agentBounds, const TilePosition& changedTile);
 
         void unlockTile(std::size_t jobId, const AgentBounds& agentBounds, const TilePosition& changedTile);
diff --git a/components/detournavigator/debug.cpp b/components/detournavigator/debug.cpp
index 5ce1464bdd..3a3430c9d3 100644
--- a/components/detournavigator/debug.cpp
+++ b/components/detournavigator/debug.cpp
@@ -1,5 +1,4 @@
 #include "debug.hpp"
-#include "exceptions.hpp"
 #include "recastmesh.hpp"
 #include "settings.hpp"
 #include "settingsutils.hpp"
@@ -17,7 +16,7 @@
 #include <filesystem>
 #include <fstream>
 #include <ostream>
-#include <string_view>
+#include <system_error>
 
 namespace DetourNavigator
 {
@@ -224,7 +223,8 @@ namespace DetourNavigator
         const auto path = pathPrefix + "recastmesh" + revision + ".obj";
         std::ofstream file(std::filesystem::path(path), std::ios::out);
         if (!file.is_open())
-            throw NavigatorException("Open file failed: " + path);
+            throw std::system_error(
+                errno, std::generic_category(), "Failed to open file to write recast mesh: " + path);
         file.exceptions(std::ios::failbit | std::ios::badbit);
         file.precision(std::numeric_limits<float>::max_exponent10);
         std::vector<float> vertices = recastMesh.getMesh().getVertices();
@@ -271,7 +271,7 @@ namespace DetourNavigator
         const auto path = pathPrefix + "all_tiles_navmesh" + revision + ".bin";
         std::ofstream file(std::filesystem::path(path), std::ios::out | std::ios::binary);
         if (!file.is_open())
-            throw NavigatorException("Open file failed: " + path);
+            throw std::system_error(errno, std::generic_category(), "Failed to open file to write navmesh: " + path);
         file.exceptions(std::ios::failbit | std::ios::badbit);
 
         NavMeshSetHeader header;