{"record":{"id":"070b934b493668b5","repo":"kubernetes/kops","slug":"error-writing-to-output-v-070b93","errorCode":null,"errorMessage":"error writing to output: %v","messagePattern":"error writing to output: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/kops/update_cluster.go","lineNumber":497,"sourceCode":"\t\t\t\t} else {\n\t\t\t\t\tfmt.Fprintf(sb, \" * to ssh to the bastion, you probably want to configure a bastionPublicName.\\n\")\n\t\t\t\t}\n\t\t\t}\n\t\t\tfmt.Fprintf(sb, \" * the ubuntu user is specific to Ubuntu. If not using Ubuntu please use the appropriate user based on your OS.\\n\")\n\t\t\tfmt.Fprintf(sb, \" * read about installing addons at: https://kops.sigs.k8s.io/addons.\\n\")\n\t\t\tfmt.Fprintf(sb, \"\\n\")\n\t\t}\n\n\t\tif !firstRun && !c.Reconcile {\n\t\t\t// TODO: Detect if rolling-update is needed\n\t\t\tfmt.Fprintf(sb, \"\\n\")\n\t\t\tfmt.Fprintf(sb, \"Changes may require instances to restart: kops rolling-update cluster\\n\")\n\t\t\tfmt.Fprintf(sb, \"\\n\")\n\t\t}\n\n\t\t_, err := out.Write(sb.Bytes())\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error writing to output: %v\", err)\n\t\t}\n\t}\n\n\treturn results, nil\n}\n\nfunc parseLifecycle(lifecycle string) (fi.Lifecycle, error) {\n\tif v, ok := fi.LifecycleNameMap[lifecycle]; ok {\n\t\treturn v, nil\n\t}\n\treturn \"\", fmt.Errorf(\"unknown lifecycle %q, available lifecycle: %s\", lifecycle, strings.Join(fi.Lifecycles.List(), \",\"))\n}\n\nfunc usesBastion(instanceGroups []*kops.InstanceGroup) bool {\n\tfor _, ig := range instanceGroups {\n\t\tif ig.Spec.Role.HasBastion() {\n\t\t\treturn true\n\t\t}","sourceCodeStart":479,"sourceCodeEnd":515,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/cmd/kops/update_cluster.go#L479-L515","documentation":"At the end of a dry-run `kops update cluster`, the generated summary buffer (cluster changes, must-remove items, instance restart notes) is written to the command's output writer. If that write fails, the command returns `error writing to output: %v`. This is an I/O failure of the destination stream, not a cluster problem.","triggerScenarios":"out.Write fails because the underlying writer broke: closed stdout pipe (e.g. `kops update cluster --dry-run | head` causing SIGPIPE/EPIPE), full disk, or the caller (test harness / RunCreateCluster / RunGetAssets) supplied a writer on a closed file or network stream.","commonSituations":"Piping kops output to `head` or `grep -q` which close the pipe early; CI log collection dropping the stream; running under systemd with a journald that blocks; buffered writers not flushed/closed by embedders.","solutions":["Redirect full output to a file instead of piping into commands that exit early (`kops update cluster ... --dry-run > plan.txt`), then inspect the file","Retry when the output destination (disk/pipe) is healthy","Fix the embedder's writer lifecycle if calling RunUpdateCluster programmatically (keep writer open, flush/close in order)"],"exampleFix":"// before\nkops update cluster c.k8s.local --dry-run | head -5\n// after\nkops update cluster c.k8s.local --dry-run > plan.txt\nhead -5 plan.txt","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"results, err := RunUpdateCluster(ctx, options)\nif errors.Is(err, syscall.EPIPE) || strings.Contains(err.Error(), \"error writing to output\") {\n\t// output stream died (e.g. SIGPIPE); rerun writing to a file\n\tf, _ := os.Create(\"plan.txt\")\n\tdefer f.Close()\n\toptions.Out = f\n\tresults, err = RunUpdateCluster(ctx, options)\n}\nif err != nil { return err }","preventionTips":["Avoid piping kops output into commands that exit early (head, grep -q); redirect to a file instead","Ensure stdout/stderr destinations in CI remain open for the process lifetime","For embedders, pass an io.Writer you control and flush/close it after RunUpdateCluster returns","Check disk space on hosts capturing large dry-run output"],"tags":["cli","io","pipe","dry-run"],"backgroundTag":"broken-pipe","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}