From 011a5e43f4b3a4442491bb80a140b1d05296b0ba Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 19 May 2026 12:25:31 +0200 Subject: [PATCH] feat(wb): surface WB-swallowed exceptions for EnvCell upload failures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 1 confirmed 26/123 Holtburg cells silently fail in WB's PrepareEnvCellMeshData / PrepareMeshData. WB's catch block at ObjectMeshManager.cs:589 calls _logger.LogError(ex, ...) — but we construct ObjectMeshManager with NullLogger, so the log is dropped. Capture the Task from PrepareMeshDataAsync (previously fire-and-forget) and attach a ContinueWith that, for EnvCell ids only when the probe is on, logs: [indoor-upload] FAILED cellId=0x... exception=: stack=[] [indoor-upload] NULL_RESULT cellId=0x... Runs on ThreadPool — non-blocking. Zero cost when ProbeIndoorUploadEnabled is off. AggregateException is unwrapped to InnerException for readability. Stack truncated to top 3 frames. Next: capture procedure, identify cause, target the fix. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/AcDream.App/Rendering/Wb/WbMeshAdapter.cs | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/AcDream.App/Rendering/Wb/WbMeshAdapter.cs b/src/AcDream.App/Rendering/Wb/WbMeshAdapter.cs index 23b2d68..0d8dee8 100644 --- a/src/AcDream.App/Rendering/Wb/WbMeshAdapter.cs +++ b/src/AcDream.App/Rendering/Wb/WbMeshAdapter.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; using AcDream.Core.Meshing; using AcDream.Core.Rendering; using Chorizite.OpenGLSDLBackend; @@ -143,13 +145,39 @@ public sealed class WbMeshAdapter : IDisposable, IWbMeshAdapter // isSetup: false — acdream's MeshRefs already carry expanded // per-part GfxObj ids (0x01XXXXXX). WB's Setup-expansion path is // unused. - _ = _meshManager.PrepareMeshDataAsync(id, isSetup: false); + var prepTask = _meshManager.PrepareMeshDataAsync(id, isSetup: false); // [indoor-upload] requested probe — only for EnvCell ids. if (RenderingDiagnostics.IsEnvCellId(id) && RenderingDiagnostics.ProbeIndoorUploadEnabled) { _pendingEnvCellRequests.Add(id); Console.WriteLine($"[indoor-upload] requested cellId=0x{id:X8}"); + + // Phase 2 — surface what WB's catch block silently swallows. + // ObjectMeshManager.PrepareMeshData has a try/catch at line 589 + // that calls _logger.LogError(ex, ...) — but we construct + // ObjectMeshManager with NullLogger.Instance so the log is + // dropped. This continuation captures the same data scoped to + // EnvCell ids only. Runs on ThreadPool; non-blocking. Zero cost + // when the probe is off. + ulong cellId = id; + _ = prepTask.ContinueWith(t => + { + if (t.IsFaulted && t.Exception is not null) + { + var ex = t.Exception.InnerException ?? t.Exception; + var stack = (ex.StackTrace ?? "").Split('\n') + .Take(3).Select(s => s.Trim()).Where(s => s.Length > 0); + Console.WriteLine( + $"[indoor-upload] FAILED cellId=0x{cellId:X8} " + + $"exception={ex.GetType().Name}: {ex.Message} " + + $"stack=[{string.Join(" | ", stack)}]"); + } + else if (t.IsCompletedSuccessfully && t.Result is null) + { + Console.WriteLine($"[indoor-upload] NULL_RESULT cellId=0x{cellId:X8}"); + } + }, TaskScheduler.Default); } } }