wavetermdev/waveterm · error

appending to file: %w

Error message

appending to file: %w

What it means

When the 8KB batch buffer fills during 'wsh file append', each batch is sent via wshclient.FileAppendCommand; a failure there is wrapped as 'appending to file: %w'. This is a mid-stream RPC failure, so earlier 8KB batches may already have been written — the file can end up partially appended.

Source

Thrown at cmd/wsh/cmd/wshcmd-file.go:307

		n, err := reader.Read(chunk)
		if err == io.EOF {
			break
		}
		if err != nil {
			return fmt.Errorf("reading input: %w", err)
		}

		if int64(buf.Len()+n) > remainingSpace {
			return fmt.Errorf("append would exceed maximum file size of %d bytes", MaxFileSize)
		}

		buf.Write(chunk[:n])

		if buf.Len() >= 8192 { // 8KB batch size
			fileData.Data64 = base64.StdEncoding.EncodeToString(buf.Bytes())
			err = wshclient.FileAppendCommand(RpcClient, fileData, &wshrpc.RpcOpts{Timeout: fileTimeout})
			if err != nil {
				return fmt.Errorf("appending to file: %w", err)
			}
			remainingSpace -= int64(buf.Len())
			buf.Reset()
		}
	}

	if buf.Len() > 0 {
		fileData.Data64 = base64.StdEncoding.EncodeToString(buf.Bytes())
		err = wshclient.FileAppendCommand(RpcClient, fileData, &wshrpc.RpcOpts{Timeout: fileTimeout})
		if err != nil {
			return fmt.Errorf("appending to file: %w", err)
		}
	}

	return nil
}

func checkFileSize(path string, maxSize int64) (*wshrpc.FileInfo, error) {

View on GitHub (pinned to a4447c1563)

Solutions

  1. Retry the append for the remaining data (already-written batches persist; skip or resume accordingly)
  2. Increase the RPC timeout for large appends on slow links
  3. Verify block connectivity and remote disk space before long appends
  4. Write to a local temp file and send one 'wsh file write' instead of many RPC round-trips

Example fix

// before
err = wshclient.FileAppendCommand(RpcClient, fileData, &wshrpc.RpcOpts{Timeout: fileTimeout})
if err != nil {
    return fmt.Errorf("appending to file: %w", err)
}
// after
err = wshclient.FileAppendCommand(RpcClient, fileData, &wshrpc.RpcOpts{Timeout: fileTimeout})
if err != nil {
    return fmt.Errorf("appending %d-byte batch (offset %d, earlier batches kept): %w", buf.Len(), sentSoFar, err)
}
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight: ensure block reachable and remote has headroom
info, err := wshclient.FileInfoCommand(RpcClient, fileData, &wshrpc.RpcOpts{Timeout: fileTimeout})
if err != nil { return err }
if info.Size+expectedInputSize > 10*1024*1024 { return errors.New("no headroom") }

Type guard

func isRetryable(err error) bool {
    return errors.Is(err, context.DeadlineExceeded) || errors.Is(err, io.ErrUnexpectedEOF)
}

Try / catch

for attempt := 0; attempt < 3; attempt++ {
    err = wshclient.FileAppendCommand(RpcClient, fileData, &wshrpc.RpcOpts{Timeout: fileTimeout})
    if err == nil { break }
    if !isRetryable(err) { return fmt.Errorf("appending to file: %w", err) }
    time.Sleep(time.Duration(1<<attempt) * time.Second)
}

Prevention

When it happens

Trigger: A FileAppendCommand RPC error mid-loop: timeout (fileTimeout) on a slow connection, disconnection from the target block, or a server-side write error (permissions, disk full) after at least one successful batch.

Common situations: Appending multi-MB streams over a slow/unstable connection where a later batch times out; remote disk filling up during the append; the target block being closed while the stream is in flight.

Related errors


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