{"record":{"id":"dcfa3ff20fa36d5b","repo":"dgraph-io/badger","slug":"block-size-cannot-be-zero","errorCode":null,"errorMessage":"Block size cannot be zero","messagePattern":"Block size cannot be zero","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"table/table.go","lineNumber":273,"sourceCode":"\n\twritten := bd.Copy(mf.Data)\n\ty.AssertTrue(written == len(mf.Data))\n\tif err := z.Msync(mf.Data); err != nil {\n\t\treturn nil, y.Wrapf(err, \"while calling msync on %s\", fname)\n\t}\n\treturn OpenTable(mf, *builder.opts)\n}\n\n// OpenTable assumes file has only one table and opens it. Takes ownership of fd upon function\n// entry. Returns a table with one reference count on it (decrementing which may delete the file!\n// -- consider t.Close() instead). The fd has to writeable because we call Truncate on it before\n// deleting. Checksum for all blocks of table is verified based on value of chkMode.\nfunc OpenTable(mf *z.MmapFile, opts Options) (*Table, error) {\n\t// BlockSize is used to compute the approximate size of the decompressed\n\t// block. It should not be zero if the table is compressed.\n\tif opts.BlockSize == 0 && opts.Compression != options.None {\n\t\t_ = mf.Close(-1)\n\t\treturn nil, errors.New(\"Block size cannot be zero\")\n\t}\n\tfileInfo, err := mf.Fd.Stat()\n\tif err != nil {\n\t\tmf.Close(-1)\n\t\treturn nil, y.Wrap(err, \"\")\n\t}\n\n\tfilename := fileInfo.Name()\n\tid, ok := ParseFileID(filename)\n\tif !ok {\n\t\tmf.Close(-1)\n\t\treturn nil, fmt.Errorf(\"Invalid filename: %s\", filename)\n\t}\n\tt := &Table{\n\t\tMmapFile:   mf,\n\t\tid:         id,\n\t\topt:        &opts,\n\t\tIsInmemory: false,","sourceCodeStart":255,"sourceCodeEnd":291,"githubUrl":"https://github.com/dgraph-io/badger/blob/2a001d466f6b71a917319a1db41f99860e16e269/table/table.go#L255-L291","documentation":"OpenTable requires a nonzero BlockSize whenever the table is compressed. BlockSize is used to size the decompression buffer for blocks, so a zero BlockSize with compression other than options.None makes block decoding impossible; OpenTable closes the mmap file and returns this error.","triggerScenarios":"Calling OpenTable with opts.Compression set to Snappy/ZSTD while opts.BlockSize is 0 (zero-value Options); reading an existing table with wrong OpenTable options where BlockSize wasn't propagated from the DB's stored options.","commonSituations":"Constructing table.Options by hand for a one-off table read and forgetting BlockSize; copying Options across Badger versions where the field was renamed or defaulted differently; tests opening tables with empty Options{} while the table was written with compression enabled.","solutions":["Set opts.BlockSize to the same block size used when the table was built (default badger block size, e.g. 4KB) whenever opts.Compression != options.None","Pass the table's original options rather than a zero-value Options{}; or set Compression to options.None if the table is truly uncompressed","Use the DB-level open path (badger.Open) instead of calling OpenTable directly so correct options are loaded from the manifest","If writing a test, mirror the writer's options: BlockSize = builder's block size"],"exampleFix":"// before\ntbl, err := table.OpenTable(mf, table.Options{Compression: options.ZSTD}) // BlockSize 0\n// after\ntbl, err := table.OpenTable(mf, table.Options{Compression: options.ZSTD, BlockSize: 4096})","handlingStrategy":"validation","validationCode":"if opts.Compression != options.None && opts.BlockSize == 0 {\n\treturn errors.New(\"BlockSize must be nonzero when compression is enabled\")\n}","typeGuard":"func openTableOptsValid(o table.Options) bool {\n\treturn o.Compression == options.None || o.BlockSize > 0\n}","tryCatchPattern":"tbl, err := table.OpenTable(mf, opts)\nif err != nil {\n\tif err.Error() == \"Block size cannot be zero\" {\n\t\topts.BlockSize = 4096 // badger default\n\t\ttbl, err = table.OpenTable(mf, opts)\n\t}\n\tif err != nil { return nil, err }\n}","preventionTips":["When enabling Snappy/ZSTD, always set BlockSize alongside Compression","Reuse the writer's options when opening tables (open via badger.Open, not raw OpenTable)","Avoid zero-value Options{} for compressed tables","Keep BlockSize identical between builder and reader options"],"tags":["options","validation","block-size"],"backgroundTag":"invalid-block-size","analyzedSha":"2a001d466f6b71a917319a1db41f99860e16e269","analyzedAt":"2026-09-05T13:00:02.264Z","contentChangedAt":"2026-09-05T13:00:02.264Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}