{"record":{"id":"f4f90762ff4c230e","repo":"microsoft/garnet","slug":"nameof-logsettings-pagesizebits-must-be-page","errorCode":null,"errorMessage":"{nameof(logSettings.PageSizeBits)} must be >= PageHeader.SizeBits {PageHeader.SizeBits}","messagePattern":"(.+?) must be >= PageHeader\\.SizeBits (.+?)","errorType":"exception","errorClass":"TsavoriteException","httpStatus":null,"severity":"error","filePath":"libs/storage/Tsavorite/cs/src/core/Allocator/AllocatorBase.cs","lineNumber":552,"sourceCode":"            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)\n                    throw new TsavoriteException($\"{nameof(rcs.PageSizeBits)} must be between {LogSettings.kMinPageSizeBits} and {LogSettings.kMaxPageSizeBits}\");\n                if (rcs.PageCount > MemoryUtils.ArrayMaxLength)","sourceCodeStart":534,"sourceCodeEnd":570,"githubUrl":"https://github.com/microsoft/garnet/blob/951b0fc6838721f89d102c2bbe1b914e8d39d700/libs/storage/Tsavorite/cs/src/core/Allocator/AllocatorBase.cs#L534-L570","documentation":"Constructor validation: logSettings.PageSizeBits must be >= PageHeader.SizeBits (6, i.e. 64 bytes), because each page must be large enough to hold its header. Under the current constants this guard is shadowed by error 222 (the [12,27] range check fires first for any value below 12), so it is effectively a defensive, near-unreachable lower bound documenting the page-header constraint.","triggerScenarios":"Only reachable if kMinPageSizeBits were ever lowered below PageHeader.SizeBits (6); today any PageSizeBits < 12 trips error 222 first. Practically unreachable with shipped constants.","commonSituations":"Not hit in practice on released code; a developer reading the validation chain may see it. Could surface only in a fork that lowers kMinPageSizeBits.","solutions":["Set PageSizeBits to at least kMinPageSizeBits (12); this automatically satisfies the PageHeader.SizeBits (6) bound.","If maintaining a fork, keep kMinPageSizeBits >= PageHeader.SizeBits."],"exampleFix":"// No realistic fix needed; ensure PageSizeBits >= 12 (kMinPageSizeBits).\nlogSettings.PageSizeBits = 12;","handlingStrategy":"validation","validationCode":"// Practically unreachable while kMinPageSizeBits (12) >= PageHeader.SizeBits (6).\n// Satisfied implicitly by keeping PageSizeBits >= 12 (see error 222).\nstatic void EnsurePageSizeAboveHeader(LogSettings s)\n{\n    const int PageHeaderSizeBits = 6;\n    if (s.PageSizeBits < PageHeaderSizeBits)\n        throw new ArgumentException($\"PageSizeBits {s.PageSizeBits} < PageHeader.SizeBits {PageHeaderSizeBits}\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat this guard as documentation; ensure PageSizeBits >= 12 and it can never fire.","If maintaining a fork that lowers kMinPageSizeBits, keep it >= PageHeader.SizeBits (6)."],"tags":["storage","configuration","log-settings","page-size","defensive"],"backgroundTag":null,"analyzedSha":"951b0fc6838721f89d102c2bbe1b914e8d39d700","analyzedAt":"2026-08-13T19:01:32.939Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}