{"record":{"id":"8e95be37c7df1b28","repo":"microsoft/garnet","slug":"nameof-logsettings-pagecount-or-nameof-logsett","errorCode":null,"errorMessage":"{nameof(logSettings.PageCount)} or {nameof(logSettings.MemorySize)} must be specified","messagePattern":"(.+?) or (.+?) must be specified","errorType":"exception","errorClass":"TsavoriteException","httpStatus":null,"severity":"error","filePath":"libs/storage/Tsavorite/cs/src/core/Allocator/AllocatorBase.cs","lineNumber":548,"sourceCode":"        {\n            var logSettings = allocatorSettings.LogSettings;\n            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)","sourceCodeStart":530,"sourceCodeEnd":566,"githubUrl":"https://github.com/microsoft/garnet/blob/951b0fc6838721f89d102c2bbe1b914e8d39d700/libs/storage/Tsavorite/cs/src/core/Allocator/AllocatorBase.cs#L530-L566","documentation":"Constructor validation in AllocatorBase: the in-memory circular buffer must be sized, and you must supply at least one of logSettings.MemorySize (bytes) or logSettings.PageCount. With both at 0 the allocator cannot decide how many pages to keep resident, so construction aborts. Note MemorySize defaults to 1L<<34 (16GiB), so this only fires when a caller explicitly set MemorySize = 0 and left PageCount = 0.","triggerScenarios":"Constructing TsavoriteKV/TsavoriteLog with `new LogSettings { MemorySize = 0, PageCount = 0, ... }`, or with a ReadOnly log where MemorySize was zeroed but PageCount was never set.","commonSituations":"Building a ReadOnly TsavoriteLog and copying a minimal-config template that zeroed MemorySize without adding PageCount; shrinking RAM footprint by setting MemorySize=0 believing PageCount would default; migrating from an older sample that set fields differently.","solutions":["Set logSettings.MemorySize to a positive value within [1<<13, 1<<62] (default 1<<34 is fine), or","Set logSettings.PageCount to at least kMinPageCount (2); for ReadOnly logs PageCount is the recommended sizing knob.","If you intended a ReadOnly log, keep MemorySize = 0 but set PageCount explicitly."],"exampleFix":"// before\nvar s = new LogSettings { LogDevice = dev, MemorySize = 0, PageCount = 0 };\n// after (readonly-style sizing)\nvar s = new LogSettings { LogDevice = dev, MemorySize = 0, PageCount = 64 };\n// or simply rely on the default MemorySize by not zeroing it","handlingStrategy":"validation","validationCode":"static void EnsureSized(LogSettings s)\n{\n    if (s.MemorySize == 0 && s.PageCount == 0)\n        throw new ArgumentException(\"Set LogSettings.MemorySize (>0) or LogSettings.PageCount (>0); both are 0.\");\n}\n\n// call before constructing TsavoriteKV/TsavoriteLog\nEnsureSized(logSettings);","typeGuard":null,"tryCatchPattern":"try { new TsavoriteLog(logSettings); }\ncatch (TsavoriteException ex) when (ex.Message.Contains(\"PageCount\") && ex.Message.Contains(\"MemorySize\") && ex.Message.Contains(\"must be specified\"))\n{ /* set MemorySize or PageCount, then recreate */ }","preventionTips":["Never zero both MemorySize and PageCount; rely on the default MemorySize (16GiB) if unsure.","For ReadOnly logs keep MemorySize=0 but always set PageCount.","Validate LogSettings in a helper before every store construction."],"tags":["storage","configuration","log-settings","memory"],"backgroundTag":null,"analyzedSha":"951b0fc6838721f89d102c2bbe1b914e8d39d700","analyzedAt":"2026-08-13T19:01:32.939Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}