{"record":{"id":"1051d69b2bbe32f8","repo":"hasura/graphql-engine","slug":"writing-output-failed-w","errorCode":null,"errorMessage":"writing output failed: %w","messagePattern":"writing output failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/commands/metadata.go","lineNumber":113,"sourceCode":"\n\treturn metadataCmd\n}\n\nfunc writeByOutputFormat(w io.Writer, b []byte, format rawOutputFormat) error {\n\tvar op errors.Op = \"commands.writeByOutputFormat\"\n\n\tswitch format {\n\tcase rawOutputFormatJSON:\n\t\tout := new(bytes.Buffer)\n\n\t\terr := json.Indent(out, b, \"\", \"  \")\n\t\tif err != nil {\n\t\t\treturn errors.E(op, err)\n\t\t}\n\n\t\t_, err = io.Copy(w, out)\n\t\tif err != nil {\n\t\t\treturn errors.E(op, fmt.Errorf(\"writing output failed: %w\", err))\n\t\t}\n\tcase rawOutputFormatYAML:\n\t\to, err := metadatautil.JSONToYAML(b)\n\t\tif err != nil {\n\t\t\treturn errors.E(op, err)\n\t\t}\n\n\t\t_, err = io.Copy(w, bytes.NewReader(o))\n\t\tif err != nil {\n\t\t\treturn errors.E(op, fmt.Errorf(\"writing output failed: %w\", err))\n\t\t}\n\tdefault:\n\t\treturn errors.E(\n\t\t\top,\n\t\t\tfmt.Errorf(\n\t\t\t\t\"output format '%v' is not supported. supported formats: %v, %v\",\n\t\t\t\tformat,\n\t\t\t\trawOutputFormatJSON,","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/hasura/graphql-engine/blob/724551b9ae87845594ef0408cff0e50eb6c90dc5/cli/commands/metadata.go#L95-L131","documentation":"This error is returned by writeByOutputFormat in the Hasura CLI when streaming the formatted JSON metadata output to the destination writer (usually stdout) fails during io.Copy. It wraps the underlying I/O error, so the real cause (broken pipe, closed stdout, disk full when redirected) is in the wrapped error chain. It only occurs in the rawOutputFormatJSON branch after the metadata has been successfully exported and indented.","triggerScenarios":"Running `hasura metadata export --output-format json` (or code calling writeByOutputFormat with rawOutputFormatJSON) where the destination writer fails mid-copy: piping output to a command that exits early (`hasura metadata export | head`), redirecting to a full filesystem, or stdout being closed by the calling process.","commonSituations":"Piping CLI output to `head`/`less` that terminates early (EPIPE), writing to a redirected file on a full disk, running in CI where stdout is captured and the runner is killed, or programmatic use of the EC writer after it was already closed.","solutions":["Inspect the wrapped error with errors.Unwrap or go-errors chain to identify the actual I/O cause (EPIPE, no space left on device, file already closed)","If piping to pagers like head/less, use a pager that reads all input or capture to a file first: `hasura metadata export > metadata.json`","Free disk space or redirect to a writable location if the destination filesystem is full","Avoid closing ec.Stdout before metadata commands finish when embedding the CLI programmatically"],"exampleFix":"# before\nhasura metadata export --output-format json | head -20\n# after (EPIPE from head exiting early)\nhasura metadata export --output-format json > metadata.json && head -20 metadata.json","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Go: capture and inspect the wrapped io error\nerr := writeByOutputFormat(ec.Stdout, b, rawOutputFormatJSON)\nif err != nil {\n  var opErr *net.OpError\n  if errors.As(err, &opErr) || strings.Contains(err.Error(), \"broken pipe\") {\n    // consumer exited early; not fatal for batch flows\n    log.Println(\"output consumer closed early:\", err)\n    return nil\n  }\n  return err\n}","preventionTips":["Redirect metadata output to files instead of piping to short-lived consumers","Keep the execution context's writer open until commands complete"],"tags":["io","stdout","metadata-export","cli"],"backgroundTag":"broken-pipe","analyzedSha":"724551b9ae87845594ef0408cff0e50eb6c90dc5","analyzedAt":"2026-08-28T07:32:55.105Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}