{"record":{"id":"9942e674eab1a555","repo":"golang/go","slug":"error-size-of-s-changed-during-reading-from-d","errorCode":null,"errorMessage":"error: size of %s changed during reading (from %d to %d bytes)","messagePattern":"error: size of (.+?) changed during reading \\(from (.+?) to (.+?) bytes\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmd/gofmt/gofmt.go","lineNumber":359,"sourceCode":"\n\t// We try to read size+1 bytes so that we can detect modifications: if we\n\t// read more than size bytes, then the file was modified concurrently.\n\t// (If that happens, we could, say, append to src to finish the read, or\n\t// proceed with a truncated buffer — but the fact that it changed at all\n\t// indicates a possible race with someone editing the file, so we prefer to\n\t// stop to avoid corrupting it.)\n\tsrc := make([]byte, size+1)\n\tn, err := io.ReadFull(in, src)\n\tswitch err {\n\tcase nil, io.EOF, io.ErrUnexpectedEOF:\n\t\t// io.ReadFull returns io.EOF (for an empty file) or io.ErrUnexpectedEOF\n\t\t// (for a non-empty file) if the file was changed unexpectedly. Continue\n\t\t// with comparing file sizes in those cases.\n\tdefault:\n\t\treturn nil, err\n\t}\n\tif n < size {\n\t\treturn nil, fmt.Errorf(\"error: size of %s changed during reading (from %d to %d bytes)\", filename, size, n)\n\t} else if n > size {\n\t\treturn nil, fmt.Errorf(\"error: size of %s changed during reading (from %d to >=%d bytes)\", filename, size, len(src))\n\t}\n\treturn src[:n], nil\n}\n\nfunc main() {\n\t// Arbitrarily limit in-flight work to 2MiB times the number of threads.\n\t//\n\t// The actual overhead for the parse tree and output will depend on the\n\t// specifics of the file, but this at least keeps the footprint of the process\n\t// roughly proportional to GOMAXPROCS.\n\tmaxWeight := (2 << 20) * int64(runtime.GOMAXPROCS(0))\n\ts := newSequencer(maxWeight, os.Stdout, os.Stderr)\n\n\t// call gofmtMain in a separate function\n\t// so that it can use defer and have them\n\t// run before the exit.","sourceCodeStart":341,"sourceCodeEnd":377,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/gofmt/gofmt.go#L341-L377","documentation":"Thrown by gofmt's source reader when io.ReadFull returns fewer bytes (n) than the size recorded by an earlier os.Stat (size), meaning the file shrank between Stat and the read. gofmt pre-allocates src as size+1 bytes and treats n<size as a concurrent modification that would corrupt formatting, so it bails rather than emit wrong output.","triggerScenarios":"Another process truncates or rewrites the file shorter between the initial Stat (which sets `size`) and io.ReadFull. Common with editors auto-saving, formatters racing, build tools rewriting generated files, or version-control operations happening during gofmt.","commonSituations":"Running gofmt in a tight watch loop while an editor saves; piping through gofmt while a code generator regenerates the same file; CI running gofmt concurrently with `go generate`; NFS/network filesystems with eventual consistency.","solutions":["Re-run gofmt once the file is stable — the condition is transient.","Stop concurrent writers (close the editor's auto-format, pause `go generate`) while gofmt runs.","For CI, run gofmt on a clean checkout without parallel generation steps.","If persistent, check for a misbehaving watcher/formatter loop that keeps truncating the file."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// run gofmt with a bounded retry on transient size-change errors:\nfor i := 0; i < 3; i++ {\n    out, err := exec.Command(\"gofmt\", file).CombinedOutput()\n    if err == nil { break }\n    if !strings.Contains(string(out), \"changed during reading\") { break }\n    time.Sleep(100 * time.Millisecond << i)\n}","preventionTips":["Do not run gofmt concurrently with editors/code generators on the same file.","In CI, run gofmt on a clean checkout without parallel generation.","Use file locking or a watch debounce if running gofmt in a loop."],"tags":["gofmt","race-condition","filesystem","concurrency"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}