{"record":{"id":"327df37ab910f9ae","repo":"golang/go","slug":"file-changed-between-reads","errorCode":null,"errorMessage":"file changed between reads","messagePattern":"file changed between reads","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmd/compile/internal/staticdata/data.go","lineNumber":142,"sourceCode":"\tif err != nil {\n\t\treturn nil, 0, err\n\t}\n\tdefer f.Close()\n\tinfo, err := f.Stat()\n\tif err != nil {\n\t\treturn nil, 0, err\n\t}\n\tif !info.Mode().IsRegular() {\n\t\treturn nil, 0, fmt.Errorf(\"not a regular file\")\n\t}\n\tsize := info.Size()\n\tif size <= 1*1024 {\n\t\tdata, err := io.ReadAll(f)\n\t\tif err != nil {\n\t\t\treturn nil, 0, err\n\t\t}\n\t\tif int64(len(data)) != size {\n\t\t\treturn nil, 0, fmt.Errorf(\"file changed between reads\")\n\t\t}\n\t\tvar sym *obj.LSym\n\t\tif readonly {\n\t\t\tsym = StringSym(pos, string(data))\n\t\t} else {\n\t\t\tsym = slicedata(pos, string(data))\n\t\t}\n\t\tif len(hashBytes) > 0 {\n\t\t\tsum := hash.Sum32(data)\n\t\t\tcopy(hashBytes, sum[:])\n\t\t}\n\t\treturn sym, size, nil\n\t}\n\tif size > maxFileSize {\n\t\t// ggloblsym takes an int32,\n\t\t// and probably the rest of the toolchain\n\t\t// can't handle such big symbols either.\n\t\t// See golang.org/issue/9862.","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/compile/internal/staticdata/data.go#L124-L160","documentation":"When embedding a small file (1KB or less), the compiler stats the file to get its size, then reads the entire content with io.ReadAll. After reading, it checks that len(data) equals the stat-reported size. If they differ, the file was modified between the stat and read operations, and this error is returned to prevent embedding inconsistent data.","triggerScenarios":"The embedded file is concurrently modified by another process between the stat() syscall and the read() syscall during compilation. The window is very small (sub-millisecond) so this requires active concurrent writes.","commonSituations":"Build systems that generate files concurrently with compilation (make -j with overlapping targets). File watchers or linters that rewrite files. Code generators that haven't finished writing when the compiler starts. Network filesystems with eventual consistency.","solutions":["Ensure file generation completes before compilation starts — serialize build steps","Use atomic file writes: write to a temp file, then os.Rename (rename is atomic on most filesystems)","Add a dependency in your build system so generated files are ready before go build","Avoid running file generators and the compiler in parallel on the same files"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Ensure embedded files are stable by snapshotting them before build\nfunc snapshotEmbedFiles(dir string) error {\n    return filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {\n        if err != nil {\n            return err\n        }\n        if !info.IsDir() {\n            // Read the file twice and compare — if it changes, fail\n            data1, err := os.ReadFile(path)\n            if err != nil {\n                return err\n            }\n            data2, err := os.ReadFile(path)\n            if err != nil {\n                return err\n            }\n            if !bytes.Equal(data1, data2) {\n                return fmt.Errorf(\"file %s is being modified concurrently — stabilize before build\", path)\n            }\n        }\n        return nil\n    })\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use atomic file writes (write to temp, then os.Rename) in all file generators","Serialize build steps so generated files are complete before go build runs","In Makefiles, add proper dependencies between generation and compilation targets","Avoid running code generators and the compiler in parallel on the same files"],"tags":["go-compiler","go-embed","file-system","race-condition","concurrency"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T06:17:24.410Z"}