stride3d/stride · warning · IOException

Crash report upload timed out.

Error message

Crash report upload timed out.

What it means

If the crash-report upload finished with zero successful landings and no recorded exception, ThrowIfNothingLanded reports it as a timeout: no part of the report reached the server within the allowed time.

Solutions

  1. Retry the upload (or leave the run directory for a later session's retry)
  2. Check network/proxy configuration for silently dropping firewalls
  3. Increase the upload timeout budget if the environment is slow, or send reports asynchronously at next startup

Example fix

// before
await sender.SendAsync(report); // blocks shutdown on slow network
// after
try { await sender.SendAsync(report); }
catch (IOException e) when (e.Message.Contains("timed out")) { /* defer to next launch */ }
Defensive patterns

Strategy: retry

Validate before calling

// pre-check endpoint reachability before attempting upload
using var ping = new HttpClient { Timeout = TimeSpan.FromSeconds(5) };
var reachable = await ping.GetAsync(dsnEndpoint) is { } resp;

Try / catch

try { await sender.SendAsync(report); }
catch (IOException e) when (e.Message.Contains("timed out"))
{ /* schedule retry at next startup */ }

Prevention

When it happens

Trigger: SendCoreAsync completes but succeeded == 0 and failure == null — all upload attempts neither failed explicitly nor landed, typically because requests exceeded the timeout window or were abandoned.

Common situations: Very slow or partially blocked networks; firewall silently dropping packets instead of refusing; an unreachable Sentry endpoint where connections hang rather than error.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/51da153f65609c7e. Report an issue: GitHub.

Appendix: source

Thrown at sources/crashreport/Stride.CrashReport/CrashReportSender.cs:211

                if (response.IsSuccessStatusCode)
                    Interlocked.Increment(ref succeeded);
                else
                    failure ??= $"HTTP {(int)response.StatusCode} {response.ReasonPhrase}";
                return response;
            }
            catch (Exception exception)
            {
                failure ??= exception.Message;
                throw;
            }
        }

        public void ThrowIfNothingLanded()
        {
            if (failure != null)
                throw new IOException("Crash report upload failed: " + failure);
            if (succeeded == 0)
                throw new IOException("Crash report upload timed out.");
        }
    }

    /// <summary>
    /// Maps report entries onto Sentry structures: searchable tags, GPU/memory contexts, log lines and
    /// undo/redo actions as breadcrumbs, everything else as extra data. The full report text stays
    /// attached as report.txt, which is exactly what the window's View report shows.
    /// </summary>
    private static void MapReport(Scope scope, CrashReportData report)
    {
        var gpus = new Dictionary<string, Dictionary<string, string>>();
        var memory = new Dictionary<string, string>();
        string activeAdapter = null;

        foreach (var (key, value) in report.Data)
        {
            switch (key)
            {

View on GitHub (pinned to 96fad776d2)