{"record":{"id":"37d6f95bb08a011a","repo":"lima-vm/lima","slug":"failed-to-write-rsync-stats-to-pager-w","errorCode":null,"errorMessage":"failed to write rsync stats to pager: %w","messagePattern":"failed to write rsync stats to pager: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"cmd/limactl/shell.go","lineNumber":678,"sourceCode":"\n\t\t\t// Write rsync dry-run output first\n\t\t\tif stats != nil {\n\t\t\t\trsyncHead := fmt.Sprintf(\"%s--- rsync dry-run statistics ---%s\", colorGray, colorNone)\n\t\t\t\tdiffHead := fmt.Sprintf(\"%s--- detailed diff --- %s\", colorGray, colorNone)\n\t\t\t\tif diffCmd == nil {\n\t\t\t\t\tdiffHead = fmt.Sprintf(\"%s--- detailed diff unavailable (`diff` not found) --- %s\", colorGray, colorNone)\n\t\t\t\t}\n\t\t\t\tcombinedOutput := fmt.Sprintf(\n\t\t\t\t\t\"%s\\n%s\\n\\n%s\\n\\n\\n%s\\n\",\n\t\t\t\t\trsyncHead,\n\t\t\t\t\tstats.String(),\n\t\t\t\t\trawOutput,\n\t\t\t\t\tdiffHead,\n\t\t\t\t)\n\n\t\t\t\tif _, err := fmt.Fprint(pipeIn, combinedOutput); err != nil {\n\t\t\t\t\t_ = pipeIn.Close()\n\t\t\t\t\treturn fmt.Errorf(\"failed to write rsync stats to pager: %w\", err)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif diffCmd != nil {\n\t\t\t\tif err := diffCmd.Run(); err != nil {\n\t\t\t\t\t// Command `diff` returns exit code 1 when files differ.\n\t\t\t\t\tvar exitErr *exec.ExitError\n\t\t\t\t\tif errors.As(err, &exitErr) && exitErr.ExitCode() >= 2 {\n\t\t\t\t\t\t_ = pipeIn.Close()\n\t\t\t\t\t\treturn fmt.Errorf(\"failed to run diff command: %w\", err)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t_ = pipeIn.Close()\n\n\t\t\tif err := lessCmd.Wait(); err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to wait for less command: %w\", err)","sourceCodeStart":660,"sourceCodeEnd":696,"githubUrl":"https://github.com/lima-vm/lima/blob/dd909d0973cd84fa35f9e1693181b4585ea616c1/cmd/limactl/shell.go#L660-L696","documentation":"limactl writes the rsync dry-run statistics and headers into the pager's stdin pipe before streaming the diff. If that write fails — typically because the pager exited early and closed the read end, producing EPIPE — this error is returned. The guest synced workdir remains preserved.","triggerScenarios":"Viewing changed contents when the pager terminates before/while the stats text is written: user quits `less` immediately (q), the pager crashes on the input, or the pipe is broken between StdinPipe creation and the Fprint.","commonSituations":"User pressing 'q' very quickly in less; PAGER set to a program that exits immediately (e.g. `cat` variants that fail, or a pager incompatible with the piped input); SIGPIPE handling differences in odd pager wrappers.","solutions":["Retry the preview and keep the pager open until output finishes (don't press q while it's writing).","Unset or fix PAGER (use `less -R`) if your pager wrapper exits early.","Choose Yes/No at the prompt instead of the preview to complete the flow.","Verify large rsync stats output isn't triggering a pager buffer/crash; test with `PAGER=less limactl shell`."],"exampleFix":"// before\nexport PAGER=\"custom-pager --quick\"  # exits early, breaks the pipe\n// after\nexport PAGER=\"less -R\"","handlingStrategy":"fallback","validationCode":"case \"${PAGER:-less}\" in *less*) echo 'standard pager, pipe-safe' ;; *) echo \"custom PAGER '${PAGER}' may exit early and break the pipe\" ;; esac","typeGuard":null,"tryCatchPattern":"// if the preview write fails, just answer the prompt without preview\nlimactl shell default || true   # rerun and choose Yes/No directly","preventionTips":["Use less (with -R) as the pager for lima previews.","Don't quit the pager while output is still streaming.","Avoid pager wrappers that exit immediately on piped input.","Treat preview as optional: Yes/No works without it."],"tags":["pager","pipe","broken-pipe"],"backgroundTag":"broken-pipe","analyzedSha":"dd909d0973cd84fa35f9e1693181b4585ea616c1","analyzedAt":"2026-09-01T14:24:59.842Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}