iOfficeAI/OfficeCLI · error · InvalidOperationException
render timed out after 120s
Error message
render timed out after 120s
What it means
Thrown by WatchServer's render path when the child `view <file> html` process does not exit within 120 seconds. A linked CancellationTokenSource cancels after 120s; on OperationCanceledException the process tree is killed and this InvalidOperationException is thrown, which the caller wraps into a 500 response. It bounds watch latency so a wedged render cannot stall the server.
Source
Thrown at src/officecli/Core/Watch/WatchServer.cs:2687
string renderErr = "";
int exitCode = -1;
using (var proc = System.Diagnostics.Process.Start(psi))
{
if (proc != null)
{
using var renderCts = CancellationTokenSource.CreateLinkedTokenSource(token);
renderCts.CancelAfter(TimeSpan.FromSeconds(120));
var drainErr = proc.StandardError.ReadToEndAsync(renderCts.Token);
var drainOut = proc.StandardOutput.ReadToEndAsync(renderCts.Token);
try
{
await proc.WaitForExitAsync(renderCts.Token);
}
catch (OperationCanceledException)
{
try { proc.Kill(entireProcessTree: true); } catch { }
throw new InvalidOperationException("render timed out after 120s");
}
renderErr = await drainErr;
_ = await drainOut;
exitCode = proc.ExitCode;
}
}
if (exitCode != 0 || !File.Exists(tmpOut))
{
var reason = string.IsNullOrWhiteSpace(renderErr) ? $"render exited {exitCode}" : renderErr.Trim();
throw new InvalidOperationException(reason);
}
html = await File.ReadAllTextAsync(tmpOut, token);
}
catch (Exception ex) when (ex is not OperationCanceledException)
{
var sb500 = new StringBuilder("{\"error\":");
AppendJsonString(sb500, $"failed to render {Path.GetFileName(newPath)}: {ex.Message}");
sb500.Append('}');View on GitHub (pinned to 1ced45e900)
Solutions
- Render a smaller or simpler document.
- Retry once; transient load can cause a one-off overrun.
- Check the renderer is not blocked on a network/font fetch.
Defensive patterns
Strategy: retry
Validate before calling
// No pre-check; mitigate by keeping documents renderable in well under 120s. // If you control the source, split very large decks into smaller files.
Try / catch
// The watch server already returns HTTP 500 with {"error":"...timed out..."}.
// Client: retry the view/refresh once; if it persists, reduce document size. Prevention
- Keep documents compact (fewer slides/smaller images) so renders finish fast.
- Treat a render-timeout response as transient and retry once.
- Watch renderer stderr for clues (font/asset stalls).
When it happens
Trigger: The document being rendered is very large/complex and the renderer exceeds 120s; the renderer process hung/deadlocked; the system is heavily loaded.
Common situations: Huge presentations/documents; a renderer with a pending font/asset fetch blocking it; resource-constrained host.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Regex pattern '{pattern}' exceeded {RegexMatchTimeout.TotalS
- Pipe communication timed out
- body read timed out
- render exited {exitCode}
- -1
AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13).
Data as JSON: /api/errors/b7bf82e5ae3b597b.
Report an issue: GitHub.