wavetermdev/waveterm · warning

failed to write data: %v

Error message

failed to write data: %v

What it means

ServeFileOption chose the option.Data branch (in-memory bytes) and set Content-Length to len(option.Data), but http.ResponseWriter.Write returned an error. Since Content-Length was already declared, a short/failed write means the response is corrupt; the handler returns this error. Typical cause: the client disconnected or canceled the request mid-response.

Source

Thrown at pkg/waveapp/waveapp.go:421

			if inm == etag {
				// Resource not modified
				w.WriteHeader(http.StatusNotModified)
				return nil
			}
		}
	}

	// Handle the content based on the option type
	switch {
	case option.FilePath != "":
		filePath := wavebase.ExpandHomeDirSafe(option.FilePath)
		http.ServeFile(w, r, filePath)

	case option.Data != nil:
		w.Header().Set("Content-Length", fmt.Sprintf("%d", len(option.Data)))
		w.WriteHeader(http.StatusOK)
		if _, err := w.Write(option.Data); err != nil {
			return fmt.Errorf("failed to write data: %v", err)
		}

	case option.File != nil:
		if bufferedData != nil {
			if _, err := w.Write(bufferedData); err != nil {
				return fmt.Errorf("failed to write buffered data: %v", err)
			}
		}
		if _, err := io.Copy(w, option.File); err != nil {
			return fmt.Errorf("failed to copy from file: %v", err)
		}

	case option.Reader != nil:
		if bufferedData != nil {
			if _, err := w.Write(bufferedData); err != nil {
				return fmt.Errorf("failed to write buffered data: %v", err)
			}
		}

View on GitHub (pinned to a4447c1563)

Solutions

  1. Verify the option.Data length matches the declared Content-Length and the data is fully loaded before serving.
  2. Check Wave logs/frontend console for request cancellation; this error is often benign client-disconnect noise.
  3. Reduce payload size or switch to option.File streaming for large content so writes happen incrementally.
  4. Ensure the handler isn't writing after the request context was canceled (check r.Context().Err()).
  5. Retry the frontend fetch; a transient disconnect will not recur.

Example fix

// before
if _, err := w.Write(option.Data); err != nil {
    return fmt.Errorf("failed to write data: %v", err)
}
// after: ignore benign client-disconnect errors
if _, err := w.Write(option.Data); err != nil && r.Context().Err() == nil {
    return fmt.Errorf("failed to write data: %v", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

if r.Context().Err() != nil {
    return nil // client already gone; nothing to write
}
if len(option.Data) == 0 {
    return fmt.Errorf("refusing to serve empty data option")
}

Try / catch

if _, err := w.Write(option.Data); err != nil {
    if r.Context().Err() != nil {
        return nil // client disconnected; benign
    }
    return fmt.Errorf("failed to write data: %v", err)
}

Prevention

When it happens

Trigger: Serving a vdom file option with Data set when the HTTP client (Wave frontend fetch) disconnects before the body completes, the request context is canceled, or the connection is reset.

Common situations: User closes/navigates the block while a large data payload is being served; frontend request timeouts aborting the download; network interruption between Wave frontend and the local HTTP handler.

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/ef3b711b74f38662. Report an issue: GitHub.