{"record":{"id":"c60f1af9eb7d02b7","repo":"apache/beam","slug":"no-data","errorCode":null,"errorMessage":"No data","messagePattern":"No data","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/core/util/ioutilx/read.go","lineNumber":40,"sourceCode":"\n\t\"github.com/apache/beam/sdks/v2/go/pkg/beam/internal/errors\"\n)\n\n// ReadN reads exactly N bytes from the reader. Fails otherwise.\nfunc ReadN(r io.Reader, n int) ([]byte, error) {\n\tret := make([]byte, n)\n\tindex := 0\n\n\tfor {\n\t\ti, err := r.Read(ret[index:])\n\t\tif i+index == n {\n\t\t\treturn ret, nil\n\t\t}\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif i == 0 {\n\t\t\treturn nil, errors.New(\"No data\")\n\t\t}\n\n\t\tindex += i\n\t}\n}\n\n// ReadNBufUnsafe reads exactly cap(buf) bytes from the reader. Fails otherwise.\n// Uses the unsafe package unsafely to convince escape analysis that the passed\n// in []byte doesn't escape this function through the io.Reader.\n// Intended for use with small, fixed sized, stack allocated buffers that have\n// no business being allocated to the heap.\n// If the io.Reader somehow retains the passed in []byte, then this should not\n// be used, and ReadN preferred.\nfunc ReadNBufUnsafe(r io.Reader, b []byte) error {\n\t// Use with parameter retaining readers at your own peril.\n\tret := *(*[]byte)(noescape(unsafe.Pointer(&b)))\n\tindex := 0\n\tn := len(ret)","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/core/util/ioutilx/read.go#L22-L58","documentation":"ReadN reads exactly n bytes from an io.Reader by looping over Read calls. If the very first Read returns 0 bytes with no error (EOF on an empty stream), there is 'No data' to decode, so it errors rather than returning a zero-length result.","triggerScenarios":"Calling ReadN on a reader positioned at EOF (empty stream), e.g. decoding an element from an exhausted byte stream via DecodeBytes/DecodeTo or makeReStream.","commonSituations":"Decoding more elements than were encoded; truncated or empty input files/streams; loop over-decoding past the last element of a coded stream.","solutions":["Stop decoding when this error occurs — it signals end-of-stream, not corruption","Check the stream/file is not empty or truncated before decoding","Ensure the producer encoded the expected number of elements","Treat it as io.EOF-equivalent in your decode loop"],"exampleFix":"// before\nfor {\n    v, err := ioutilx.ReadN(r, n)\n    if err != nil { return err }\n}\n// after\nfor {\n    v, err := ioutilx.ReadN(r, n)\n    if err != nil {\n        if err.Error() == \"No data\" || err == io.EOF { return nil } // clean end of stream\n        return err\n    }\n}","handlingStrategy":"try-catch","validationCode":"// check stream has data before decoding\nif f == nil { return errors.New(\"nil reader\") }\nif fi, err := f.Stat(); err == nil && fi.Size() == 0 { return io.EOF }","typeGuard":null,"tryCatchPattern":"data, err := ioutilx.ReadN(r, n)\nif err != nil {\n    if err.Error() == \"No data\" || errors.Is(err, io.EOF) { return io.EOF }\n    return err\n}","preventionTips":["Break decode loops on 'No data' exactly as on io.EOF","Track expected element counts when encoding/decoding pairs","Validate input files/streams are non-empty and untruncated","Wrap readers so EOF surfaces consistently"],"tags":["go","io","decoding","end-of-stream"],"backgroundTag":"empty-response-body","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}