{"record":{"id":"9476aaac60d6191d","repo":"wavetermdev/waveterm","slug":"appending-to-file-w","errorCode":null,"errorMessage":"appending to file: %w","messagePattern":"appending to file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/wsh/cmd/wshcmd-file.go","lineNumber":307,"sourceCode":"\t\tn, err := reader.Read(chunk)\n\t\tif err == io.EOF {\n\t\t\tbreak\n\t\t}\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"reading input: %w\", err)\n\t\t}\n\n\t\tif int64(buf.Len()+n) > remainingSpace {\n\t\t\treturn fmt.Errorf(\"append would exceed maximum file size of %d bytes\", MaxFileSize)\n\t\t}\n\n\t\tbuf.Write(chunk[:n])\n\n\t\tif buf.Len() >= 8192 { // 8KB batch size\n\t\t\tfileData.Data64 = base64.StdEncoding.EncodeToString(buf.Bytes())\n\t\t\terr = wshclient.FileAppendCommand(RpcClient, fileData, &wshrpc.RpcOpts{Timeout: fileTimeout})\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"appending to file: %w\", err)\n\t\t\t}\n\t\t\tremainingSpace -= int64(buf.Len())\n\t\t\tbuf.Reset()\n\t\t}\n\t}\n\n\tif buf.Len() > 0 {\n\t\tfileData.Data64 = base64.StdEncoding.EncodeToString(buf.Bytes())\n\t\terr = wshclient.FileAppendCommand(RpcClient, fileData, &wshrpc.RpcOpts{Timeout: fileTimeout})\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"appending to file: %w\", err)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc checkFileSize(path string, maxSize int64) (*wshrpc.FileInfo, error) {","sourceCodeStart":289,"sourceCodeEnd":325,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/cmd/wsh/cmd/wshcmd-file.go#L289-L325","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Retry the append for the remaining data (already-written batches persist; skip or resume accordingly)","Increase the RPC timeout for large appends on slow links","Verify block connectivity and remote disk space before long appends","Write to a local temp file and send one 'wsh file write' instead of many RPC round-trips"],"exampleFix":"// before\nerr = wshclient.FileAppendCommand(RpcClient, fileData, &wshrpc.RpcOpts{Timeout: fileTimeout})\nif err != nil {\n    return fmt.Errorf(\"appending to file: %w\", err)\n}\n// after\nerr = wshclient.FileAppendCommand(RpcClient, fileData, &wshrpc.RpcOpts{Timeout: fileTimeout})\nif err != nil {\n    return fmt.Errorf(\"appending %d-byte batch (offset %d, earlier batches kept): %w\", buf.Len(), sentSoFar, err)\n}","handlingStrategy":"retry","validationCode":"// pre-flight: ensure block reachable and remote has headroom\ninfo, err := wshclient.FileInfoCommand(RpcClient, fileData, &wshrpc.RpcOpts{Timeout: fileTimeout})\nif err != nil { return err }\nif info.Size+expectedInputSize > 10*1024*1024 { return errors.New(\"no headroom\") }","typeGuard":"func isRetryable(err error) bool {\n    return errors.Is(err, context.DeadlineExceeded) || errors.Is(err, io.ErrUnexpectedEOF)\n}","tryCatchPattern":"for attempt := 0; attempt < 3; attempt++ {\n    err = wshclient.FileAppendCommand(RpcClient, fileData, &wshrpc.RpcOpts{Timeout: fileTimeout})\n    if err == nil { break }\n    if !isRetryable(err) { return fmt.Errorf(\"appending to file: %w\", err) }\n    time.Sleep(time.Duration(1<<attempt) * time.Second)\n}","preventionTips":["Retry transient RPC failures with backoff on batch flushes","Track how many bytes were flushed so retries can resume, not duplicate","Increase timeout for multi-MB appends over slow links","Monitor remote disk space for long append jobs"],"tags":["rpc","append","network","partial-write"],"backgroundTag":"rpc-call-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}