{"record":{"id":"8509c60cdc3c78b9","repo":"wavetermdev/waveterm","slug":"reading-input-w","errorCode":null,"errorMessage":"reading input: %w","messagePattern":"reading input: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/wsh/cmd/wshcmd-file-util.go","lineNumber":70,"sourceCode":"\t// First truncate the file with an empty write\n\temptyWrite := fileData\n\temptyWrite.Data64 = \"\"\n\terr := wshclient.FileWriteCommand(RpcClient, emptyWrite, &wshrpc.RpcOpts{Timeout: fileTimeout})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"initializing file with empty write: %w\", err)\n\t}\n\n\tconst chunkSize = wshrpc.FileChunkSize // 32KB chunks\n\tbuf := make([]byte, chunkSize)\n\ttotalWritten := int64(0)\n\n\tfor {\n\t\tn, err := reader.Read(buf)\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\t// Check total size\n\t\ttotalWritten += int64(n)\n\t\tif totalWritten > MaxFileSize {\n\t\t\treturn fmt.Errorf(\"input exceeds maximum file size of %d bytes\", MaxFileSize)\n\t\t}\n\n\t\t// Prepare and send chunk\n\t\tchunk := buf[:n]\n\t\tappendData := fileData\n\t\tappendData.Data64 = base64.StdEncoding.EncodeToString(chunk)\n\n\t\terr = wshclient.FileAppendCommand(RpcClient, appendData, &wshrpc.RpcOpts{Timeout: int64(fileTimeout)})\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"appending chunk to file: %w\", err)\n\t\t}\n\t}","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/cmd/wsh/cmd/wshcmd-file-util.go#L52-L88","documentation":"While streaming the input, each reader.Read() error other than io.EOF aborts the transfer wrapped as \"reading input\". The library surfaces the underlying reader failure (stdin pipe, socket, or file read) instead of silently truncating the destination file.","triggerScenarios":"reader.Read(buf) returns a non-EOF error during `wsh` streaming: broken stdin pipe, disk read error on the source file, or network reset when reading from a remote source.","commonSituations":"Upstream producer in a pipe crashed (SIGPIPE/broken pipe); reading from a file that was truncated or became unreadable mid-transfer; network hiccup during remote streaming.","solutions":["Check the wrapped inner error to identify the failing source (stdin, local file, or socket).","Re-run the command after fixing the upstream producer in the pipe.","Verify the source file is readable and not being concurrently modified.","Note the destination file was already truncated — rewrite it fully after fixing the source."],"exampleFix":"// before\ngenerator-that-crashes | wsh cp - out.bin   # partial/failed\n// after\ngenerator-that-crashes > tmp.bin && wsh cp tmp.bin out.bin","handlingStrategy":"try-catch","validationCode":"src, err := os.Open(localPath)\nif err != nil {\n    return fmt.Errorf(\"source unreadable before streaming: %w\", err)\n}\ndefer src.Close()","typeGuard":null,"tryCatchPattern":"if err := streamWriteToFile(fileData, reader); err != nil {\n    if strings.Contains(err.Error(), \"reading input\") {\n        // note: destination already truncated; fix source and rewrite fully\n    }\n}","preventionTips":["Ensure upstream pipe producers won't crash mid-transfer","Avoid reading files that are concurrently truncated/rotated","Buffer to a temp file first for untrusted sources"],"tags":["io","streaming","pipe"],"backgroundTag":"io-read-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}