{"record":{"id":"9a853ea4fb7845f0","repo":"microsoft/FASTER","slug":"objects-in-key-value-but-object-log-not-provided-during","errorCode":null,"errorMessage":"Objects in key/value, but object log not provided during creation of FASTER instance","messagePattern":"Objects in key/value, but object log not provided during creation of FASTER instance","errorType":"exception","errorClass":"FasterException","httpStatus":null,"severity":"error","filePath":"cs/src/core/Allocator/GenericAllocator.cs","lineNumber":83,"sourceCode":"\n            if ((!valueBlittable) && (settings.LogDevice as NullDevice == null) && ((SerializerSettings == null) || (SerializerSettings.valueSerializer == null)))\n            {\n#if DEBUG\n                if (typeof(Value) != typeof(byte[]) && typeof(Value) != typeof(string))\n                    Debug.WriteLine(\"Value is not blittable, but no serializer specified via SerializerSettings. Using (slow) DataContractSerializer as default.\");\n#endif\n                SerializerSettings.valueSerializer = ObjectSerializer.Get<Value>();\n            }\n\n            values = new Record<Key, Value>[BufferSize][];\n            segmentOffsets = new long[SegmentBufferSize];\n\n            objectLogDevice = settings.ObjectLogDevice;\n\n            if ((settings.LogDevice as NullDevice == null) && (KeyHasObjects() || ValueHasObjects()))\n            {\n                if (objectLogDevice == null)\n                    throw new FasterException(\"Objects in key/value, but object log not provided during creation of FASTER instance\");\n                if (objectLogDevice.SegmentSize != -1)\n                    throw new FasterException(\"Object log device should not have fixed segment size. Set preallocateFile to false when calling CreateLogDevice for object log\");\n            }\n        }\n\n        internal override int OverflowPageCount => overflowPagePool.Count;\n\n        public override void Reset()\n        {\n            base.Reset();\n            objectLogDevice.Reset();\n            for (int index = 0; index < BufferSize; index++)\n            {\n                ReturnPage(index);\n            }\n\n            Array.Clear(segmentOffsets, 0, segmentOffsets.Length);\n            Initialize();","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/microsoft/FASTER/blob/321d872eabda6a0345c8bd76419f89723ed864ae/cs/src/core/Allocator/GenericAllocator.cs#L65-L101","documentation":"Thrown by the GenericAllocator constructor when the key or value type contains managed object references, the primary LogDevice is a real (non-Null) device, but settings.ObjectLogDevice is null. Unlike error 31, this is the branch guarded on NullDevice log plus has-objects: FASTER would need to serialize objects to disk and has nowhere to put them. Construction is aborted.","triggerScenarios":"GenericAllocator creation with KeyHasObjects() || ValueHasObjects() true, LogDevice not a NullDevice, and ObjectLogDevice == null.","commonSituations":"Switching key/value types from blittable primitives (long, int) to classes/strings without updating LogSettings; configuring devices once for a blittable workload then reusing them for an object workload; partial NullDevice setups where only the main log is null-device.","solutions":["Assign LogSettings.ObjectLogDevice = Devices.CreateLogDevice(\"objectlog.log\", preallocateFile: false).","If objects should stay in memory only, make both LogDevice and ObjectLogDevice NullDevice instances.","Verify the generic key/value arguments actually need objects; using blittable types avoids the object-log requirement entirely."],"exampleFix":"// before\nvar settings = new LogSettings { LogDevice = Devices.CreateLogDevice(\"data.log\") }; // class Key used\n\n// after\nvar settings = new LogSettings\n{\n    LogDevice = Devices.CreateLogDevice(\"data.log\"),\n    ObjectLogDevice = Devices.CreateLogDevice(\"data.obj.log\", preallocateFile: false)\n};","handlingStrategy":"validation","validationCode":"bool hasObjects = typeof(K).IsClass || !Blittable<K>.IsBlittable() || typeof(V).IsClass || !Blittable<V>.IsBlittable();\nif (hasObjects && !(settings.LogDevice is NullDevice) && settings.ObjectLogDevice == null)\n    settings.ObjectLogDevice = Devices.CreateLogDevice(\"data.obj.log\", preallocateFile: false);","typeGuard":"static bool ObjectLogConfigured(LogSettings s, bool keyOrValueHasObjects)\n    => !keyOrValueHasObjects || s.LogDevice is NullDevice || s.ObjectLogDevice != null;","tryCatchPattern":"try\n{\n    return new FASTERKeyedStore(settings);\n}\ncatch (FasterException ex) when (ex.Message.Contains(\"object log not provided\"))\n{\n    settings.LogSettings.ObjectLogDevice = Devices.CreateLogDevice(\"data.obj.log\", preallocateFile: false);\n    return new FASTERKeyedStore(settings);\n}","preventionTips":["Re-check device settings whenever you change key/value generic types from blittable to object-based.","Keep LogSettings creation type-aware: derive whether an object log is required from typeof(Key)/typeof(Value).","Write an integration test that constructs the store with production-like settings on every settings change."],"tags":["faster","configuration","devices","object-log"],"backgroundTag":"missing-required-config-field","analyzedSha":"321d872eabda6a0345c8bd76419f89723ed864ae","analyzedAt":"2026-09-15T22:18:00.693Z","contentChangedAt":"2026-09-15T22:18:00.693Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}