{"record":{"id":"3bd66f0a6c268661","repo":"microsoft/garnet","slug":"nameof-logsettings-pagesizebits-must-be-between","errorCode":null,"errorMessage":"{nameof(logSettings.PageSizeBits)} must be between {LogSettings.kMinPageSizeBits} and {LogSettings.kMaxPageSizeBits}","messagePattern":"(.+?) must be between (.+?) and (.+?)","errorType":"exception","errorClass":"TsavoriteException","httpStatus":null,"severity":"error","filePath":"libs/storage/Tsavorite/cs/src/core/Allocator/AllocatorBase.cs","lineNumber":550,"sourceCode":"            var evictCallback = allocatorSettings.evictCallback;\n            var epoch = allocatorSettings.epoch;\n            var flushCallback = allocatorSettings.flushCallback;\n            IsReadCache = allocatorSettings.IsReadCache;\n\n            this.storeFunctions = storeFunctions;\n            _wrapper = wrapperCreator(this);\n\n            // Pre-bind the instance-method delegate once so the pending-IO hot path does\n            // not allocate a fresh DeviceIOCompletionCallback per AsyncGetFromDisk call.\n            asyncGetFromDiskCallbackDelegate = AsyncGetFromDiskCallback;\n\n            this.transientObjectIdMap = transientObjectIdMap;\n\n            // Validation\n            if (logSettings.PageCount == 0 && logSettings.MemorySize == 0)\n                throw new TsavoriteException($\"{nameof(logSettings.PageCount)} or {nameof(logSettings.MemorySize)} must be specified\");\n            if (logSettings.PageSizeBits < LogSettings.kMinPageSizeBits || logSettings.PageSizeBits > LogSettings.kMaxPageSizeBits)\n                throw new TsavoriteException($\"{nameof(logSettings.PageSizeBits)} must be between {LogSettings.kMinPageSizeBits} and {LogSettings.kMaxPageSizeBits}\");\n            if (logSettings.PageSizeBits < PageHeader.SizeBits)\n                throw new TsavoriteException($\"{nameof(logSettings.PageSizeBits)} must be >= PageHeader.SizeBits {PageHeader.SizeBits}\");\n            if (logSettings.PageCount > MemoryUtils.ArrayMaxLength)\n                throw new TsavoriteException($\"{nameof(logSettings.PageCount)} must be less than or equal to the maximum array length ({MemoryUtils.ArrayMaxLength})\");\n            if (logSettings.SegmentSizeBits < LogSettings.kMinMainLogSegmentSizeBits || logSettings.SegmentSizeBits > LogSettings.kMaxSegmentSizeBits)\n                throw new TsavoriteException($\"{nameof(logSettings.SegmentSizeBits)} must be between {LogSettings.kMinMainLogSegmentSizeBits} and {LogSettings.kMaxSegmentSizeBits}\");\n            if (logSettings.MemorySize != 0 && (logSettings.MemorySize < 1L << LogSettings.kMinMemorySizeBits || logSettings.MemorySize > 1L << LogSettings.kMaxMemorySizeBits))\n                throw new TsavoriteException($\"{nameof(logSettings.MemorySize)} must be between {1L << LogSettings.kMinMemorySizeBits} and {1L << LogSettings.kMaxMemorySizeBits}, or may be 0 for ReadOnly TsavoriteLog\");\n            if ((logSettings.MemorySize != 0) && (logSettings.MemorySize < (1L << logSettings.PageSizeBits) * LogSettings.kMinPageCount))\n                throw new TsavoriteException($\"{nameof(logSettings.MemorySize)} must be at least {LogSettings.kMinPageCount}x the page size ({1L << logSettings.PageSizeBits})\");\n            if (logSettings.MutableFraction < 0.0 || logSettings.MutableFraction > 1.0)\n                throw new TsavoriteException($\"{nameof(logSettings.MutableFraction)} must be >= 0.0 and <= 1.0\");\n            if (logSettings.ReadCacheSettings is not null)\n            {\n                var rcs = logSettings.ReadCacheSettings;\n                if (rcs.PageCount == 0 && rcs.MemorySize == 0)\n                    throw new TsavoriteException($\"{nameof(rcs.PageCount)} or {nameof(rcs.MemorySize)} must be specified\");\n                if (rcs.PageSizeBits < LogSettings.kMinPageSizeBits || rcs.PageSizeBits > LogSettings.kMaxPageSizeBits)","sourceCodeStart":532,"sourceCodeEnd":568,"githubUrl":"https://github.com/microsoft/garnet/blob/951b0fc6838721f89d102c2bbe1b914e8d39d700/libs/storage/Tsavorite/cs/src/core/Allocator/AllocatorBase.cs#L532-L568","documentation":"Constructor validation: logSettings.PageSizeBits must fall in [LogSettings.kMinPageSizeBits, LogSettings.kMaxPageSizeBits] = [12, 27], i.e. page size between 4KiB and 128MiB. Pages are the unit of flush and eviction, and the bit width is baked into offset arithmetic, so out-of-range values are rejected. Default is 25 (32MiB).","triggerScenarios":"Setting `logSettings.PageSizeBits = 10` (4KiB page desired but expressed below the floor) or `= 30` (above the 128MiB ceiling) when constructing the store.","commonSituations":"Confusing bits and bytes (setting PageSizeBits=4096 thinking it means 4096 bytes); tuning page size for a small-cache benchmark below the 4KiB floor; copying a config snippet written against different constants.","solutions":["Set PageSizeBits to a value in [12, 27]; keep the default 25 unless you have measured a reason to change it.","Remember PageSizeBits is a power-of-two exponent in BITS, not a byte count (12 => 4096 bytes).","If you need very small pages for testing, use the floor 12 (4KiB); if you need huge pages, do not exceed 27."],"exampleFix":"// before\nlogSettings.PageSizeBits = 10;   // intent: 1KiB pages -> below floor\n// after\nlogSettings.PageSizeBits = 12;    // 4KiB, the minimum allowed","handlingStrategy":"validation","validationCode":"const int MinPageBits = 12, MaxPageBits = 27; // mirror LogSettings constants\nstatic int ClampPageSizeBits(int bits) =>\n    bits < MinPageBits ? MinPageBits : bits > MaxPageBits ? MaxPageBits : bits;\n\nlogSettings.PageSizeBits = ClampPageSizeBits(logSettings.PageSizeBits);","typeGuard":null,"tryCatchPattern":"try { new TsavoriteKV<K,V>(logSettings, ...); }\ncatch (TsavoriteException ex) when (ex.Message.Contains(\"PageSizeBits\") && ex.Message.Contains(\"between\"))\n{ /* clamp PageSizeBits to [12,27] and recreate */ }","preventionTips":["Remember PageSizeBits is a bit exponent, not bytes (12 => 4KiB).","Surface page-size config as bytes in your own settings, then convert with Log2 and clamp to [12,27].","Unit-test the boundary values (12 and 27) in your config loader."],"tags":["storage","configuration","log-settings","page-size"],"backgroundTag":null,"analyzedSha":"951b0fc6838721f89d102c2bbe1b914e8d39d700","analyzedAt":"2026-08-13T19:01:32.939Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}