{"record":{"id":"a31b9c2938a5e2f2","repo":"hashicorp/nomad","slug":"failed-to-write-string-to-eventstream-json-chars","errorCode":null,"errorMessage":"failed to write string to eventstream.json; chars written: %d, Err: %w","messagePattern":"failed to write string to eventstream\\.json; chars written: (.+?), Err: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"command/operator_debug.go","lineNumber":998,"sourceCode":"\t\t\t\teventCount++\n\t\t\t\tc.verboseOutf(\"Event: %4d, Index: %d, Topic: %-10s, Type: %s, FilterKeys: %s\", eventCount, e.Index, e.Topic, e.Type, e.FilterKeys)\n\n\t\t\t\tbytes, err := json.Marshal(e)\n\t\t\t\tif err != nil {\n\t\t\t\t\terrCount++\n\t\t\t\t\tmErrs = multierror.Append(mErrs, fmt.Errorf(\"failed to marshal json from Topic: %s, Type: %s, Err: %w\", e.Topic, e.Type, err))\n\t\t\t\t}\n\n\t\t\t\tn, err := fh.Write(bytes)\n\t\t\t\tif err != nil {\n\t\t\t\t\terrCount++\n\t\t\t\t\tmErrs = multierror.Append(mErrs, fmt.Errorf(\"failed to write bytes to eventstream.json; bytes written: %d, Err: %w\", n, err))\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tn, err = fh.WriteString(\"\\n\")\n\t\t\t\tif err != nil {\n\t\t\t\t\terrCount++\n\t\t\t\t\tmErrs = multierror.Append(mErrs, fmt.Errorf(\"failed to write string to eventstream.json; chars written: %d, Err: %w\", n, err))\n\t\t\t\t}\n\t\t\t}\n\t\tcase <-c.ctx.Done():\n\t\t\tc.verboseOutf(\"Event stream captured %d events, %d frames, %d heartbeats, %d errors\", eventCount, channelEventCount, heartbeatCount, errCount)\n\t\t\treturn mErrs.ErrorOrNil()\n\t\t}\n\t}\n}\n\n// collectAgentHosts calls collectAgentHost for each selected node\nfunc (c *OperatorDebugCommand) collectAgentHosts(client *api.Client) {\n\tfor _, n := range c.nodeIDs {\n\t\tc.collectAgentHost(clientDir, n, client)\n\t}\n\n\tfor _, n := range c.serverIDs {\n\t\tc.collectAgentHost(serverDir, n, client)\n\t}","sourceCodeStart":980,"sourceCodeEnd":1016,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/command/operator_debug.go#L980-L1016","documentation":"After writing each event's JSON bytes, captureEventStream writes a trailing \"\\n\" via fh.WriteString to keep eventstream.json line-delimited. If that small write fails, the error is recorded in the multierror with the number of chars written. Like the bytes-write error, it signals the capture file became unwritable mid-run.","triggerScenarios":"fh.WriteString(\"\\n\") returns an error after a successful bytes write — disk just filled, file closed/unlinked, I/O error, or fd exhaustion surfaced on the next write.","commonSituations":"Disk hitting 0 bytes between two writes of the same event; concurrent rotation/cleanup of the capture dir; NFS or flaky volume dropping the connection mid-capture.","solutions":["Free disk space — a failure here commonly means the volume filled within the previous write","Check n in the message (usually 0) and whether the preceding event bytes wrote fully","Ensure nothing concurrently deletes or rotates eventstream.json during capture","Re-run the capture to produce a complete, consistently newline-delimited file"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if st, err := fh.Stat(); err != nil {\n\treturn fmt.Errorf(\"capture file handle unusable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"n, err := fh.WriteString(\"\\n\")\nif err != nil {\n\terrs = multierror.Append(errs, fmt.Errorf(\"failed to write string to eventstream.json; chars written: %d, Err: %w\", n, err))\n}","preventionTips":["Free disk space before starting: a full volume can fail between two adjacent writes","Keep the capture dir free of concurrent cleanup/rotation jobs","Use stable local storage rather than flaky network mounts for captures"],"tags":["filesystem","io","durability"],"backgroundTag":"file-write-failed","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}