microsoft/typescript-go · error
api: failed to write server timing response: %v
Error message
api: failed to write server timing response: %v
What it means
While handling the $/getServerTiming meta-request, SyncConn failed to write the response and panics with the write error. The transport itself is broken (closed pipe/conn), so the server deliberately crashes rather than silently drop the timing reply.
Source
Thrown at internal/api/conn_sync.go:93
c.handleNotification(ctx, msg)
} else {
// Responses are not expected in the main loop - they are read inline by Call().
return errors.New("api: unexpected response message in sync connection")
}
}
}
// handleRequest processes an incoming request.
func (c *SyncConn) handleRequest(ctx context.Context, msg *Message) {
// Intercept the meta-requests for collected server timing before dispatching
// to the handler, so they are answered directly and not themselves recorded.
switch msg.Method {
case string(MethodGetServerTiming):
c.mu.Lock()
writeErr := c.protocol.WriteResponse(msg.ID, serverTimingSnapshot(c.timing))
c.mu.Unlock()
if writeErr != nil {
panic(fmt.Sprintf("api: failed to write server timing response: %v", writeErr))
}
return
case string(MethodResetServerTiming):
if c.timing != nil {
c.timing.reset()
}
c.mu.Lock()
writeErr := c.protocol.WriteResponse(msg.ID, nil)
c.mu.Unlock()
if writeErr != nil {
panic(fmt.Sprintf("api: failed to write reset server timing response: %v", writeErr))
}
return
}
var result any
var err error
View on GitHub (pinned to 1bcfa18d79)
Solutions
- Ensure clients wait for outstanding meta-request responses before closing the connection
- Gracefully shut down: stop the read loop before closing the transport
- If it recurs in production, capture the write error (broken pipe vs reset) to find who closes first
- Treat as a shutdown-race symptom: reproduce with connection-close timing under debug
Defensive patterns
Strategy: try-catch
Try / catch
// client side: keep the connection open until all meta-request responses arrive
ctx, cancel := context.WithTimeout(ctx, 2*time.Second)
_, err := conn.Call(ctx, "getServerTiming", nil)
if err != nil { /* transport closed mid-reply: retry on a fresh connection */ } Prevention
- Wait for responses before closing connections
- Drain pending requests during shutdown
- Reproduce close/reply races with timing logs before shipping clients
When it happens
Trigger: Client closed the connection (or crashed) between sending getServerTiming and the server's response write; I/O error on the underlying transport; shutdown racing an in-flight meta-request.
Common situations: Editor/LSP client timing out and closing the connection right as it polls server timings; tests tearing down connections without draining pending requests.
Related errors
- api: failed to write reset server timing response: %v
- -32603
- api: remote error [%d]: %s
- api: unexpected response message in sync connection
- -32603
AI-assisted analysis of microsoft/typescript-go@1bcfa18d79 (2026-08-16).
Data as JSON: /api/errors/6022dc60c2766ecf.
Report an issue: GitHub.