{"record":{"id":"62abcbe37b878579","repo":"gastownhall/beads","slug":"directory-size-overflows-int64-at-s","errorCode":null,"errorMessage":"directory size overflows int64 at %s","messagePattern":"directory size overflows int64 at (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/directory_size.go","lineNumber":57,"sourceCode":"\tvar size int64\n\terr := walk(root, func(path string, info os.FileInfo, walkErr error) error {\n\t\tif err := ctx.Err(); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif walkErr != nil {\n\t\t\tif path != root && errors.Is(walkErr, fs.ErrNotExist) {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\treturn walkErr\n\t\t}\n\t\tif info == nil {\n\t\t\treturn fmt.Errorf(\"walk returned no file information for %s\", path)\n\t\t}\n\t\tif info.IsDir() {\n\t\t\treturn nil\n\t\t}\n\t\tif info.Size() < 0 || info.Size() > math.MaxInt64-size {\n\t\t\treturn fmt.Errorf(\"directory size overflows int64 at %s\", path)\n\t\t}\n\t\tsize += info.Size()\n\t\treturn nil\n\t})\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn size, nil\n}\n","sourceCodeStart":39,"sourceCodeEnd":67,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/directory_size.go#L39-L67","documentation":"While summing file sizes into an int64, MeasureDirectorySize checks each file before adding: a negative size or one that would push the running total past math.MaxInt64 aborts the measurement. This protects the caller from a silent integer overflow producing a bogus (possibly negative) directory size. It fires only when the tree contains files with nonsensical sizes or a total exceeding ~8 exabytes.","triggerScenarios":"filepath.Walk returns a FileInfo whose Size() is negative (sparse/odd files, corrupted metadata) or the accumulated size plus this file's size would exceed math.MaxInt64 during MeasureDirectorySize.","commonSituations":"Corrupted filesystem metadata or exotic virtual files reporting negative sizes; measuring an enormous tree (multi-exabyte aggregates, usually in tests with mocked FileInfo since real trees rarely reach MaxInt64).","solutions":["Identify the path named in the error and inspect its reported size (ls -l / stat); replace or repair the file if its metadata is corrupt.","If one file reports a negative size, check the filesystem/driver; on network or FUSE mounts, remount or update the filesystem driver.","If the total genuinely exceeds int64, split the measurement into multiple roots or track the size as big.Int / uint128 instead of int64.","Exclude pathological files from the measured tree (e.g. move them out or filter them) if they are not part of the live data you need to size."],"exampleFix":"// before: trusting one int64 total for an unbounded tree\nsize += info.Size()\n// after: guard per file (as the library does) or pre-check the biggest file\nif info.Size() < 0 || info.Size() > math.MaxInt64-size {\n    return fmt.Errorf(\"directory size overflows int64 at %s\", path)\n}\nsize += info.Size()","handlingStrategy":"validation","validationCode":"func saneFileSize(n int64) bool { return n >= 0 }","typeGuard":"func canAccumulate(total, next int64) bool {\n    return next >= 0 && next <= math.MaxInt64-total\n}","tryCatchPattern":"size, err := storage.MeasureDirectorySize(ctx, root)\nvar overflowErr = errors.New(\"directory size overflows\")\nif err != nil && strings.Contains(err.Error(), \"overflows int64\") {\n    // fall back to a big.Int or per-subtree measurement\n}","preventionTips":["For trees expected to be huge, measure per-subdirectory and sum with big.Int instead of one int64.","Audit mounts serving the measured tree (FUSE/network) for files reporting negative sizes.","Keep the per-file overflow guard in any custom size-accumulating walker."],"tags":["filesystem","go","overflow","int64"],"backgroundTag":"integer-overflow","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}