microsoft/FASTER · error · FasterException
Objects in key/value, but object log not provided during…
Error message
Objects in key/value, but object log not provided during creation of FASTER instance
What it means
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.
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.
Example fix
// before
var settings = new LogSettings { LogDevice = Devices.CreateLogDevice("data.log") }; // class Key used
// after
var settings = new LogSettings
{
LogDevice = Devices.CreateLogDevice("data.log"),
ObjectLogDevice = Devices.CreateLogDevice("data.obj.log", preallocateFile: false)
}; Defensive patterns
Strategy: validation
Validate before calling
bool hasObjects = typeof(K).IsClass || !Blittable<K>.IsBlittable() || typeof(V).IsClass || !Blittable<V>.IsBlittable();
if (hasObjects && !(settings.LogDevice is NullDevice) && settings.ObjectLogDevice == null)
settings.ObjectLogDevice = Devices.CreateLogDevice("data.obj.log", preallocateFile: false); Type guard
static bool ObjectLogConfigured(LogSettings s, bool keyOrValueHasObjects)
=> !keyOrValueHasObjects || s.LogDevice is NullDevice || s.ObjectLogDevice != null; Try / catch
try
{
return new FASTERKeyedStore(settings);
}
catch (FasterException ex) when (ex.Message.Contains("object log not provided"))
{
settings.LogSettings.ObjectLogDevice = Devices.CreateLogDevice("data.obj.log", preallocateFile: false);
return new FASTERKeyedStore(settings);
} Prevention
- 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.
When it happens
Trigger: GenericAllocator creation with KeyHasObjects() || ValueHasObjects() true, LogDevice not a NullDevice, and ObjectLogDevice == null.
Common situations: 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.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- LogSettings.ObjectLogDevice needs to be specified (e.g.…
- Object log device should not have fixed segment size. Set…
- LogSettings.LogDevice needs to be specified (e.g., use…
- Segment ( ) must be at least of page size ( )
- Memory size ( ) must be configured to be either 1 (i.e., 0…
AI-assisted analysis of microsoft/FASTER@321d872eab (2026-09-15).
Data as JSON: /api/errors/9a853ea4fb7845f0.
Report an issue: GitHub.
Appendix: source
Thrown at cs/src/core/Allocator/GenericAllocator.cs:83
if ((!valueBlittable) && (settings.LogDevice as NullDevice == null) && ((SerializerSettings == null) || (SerializerSettings.valueSerializer == null)))
{
#if DEBUG
if (typeof(Value) != typeof(byte[]) && typeof(Value) != typeof(string))
Debug.WriteLine("Value is not blittable, but no serializer specified via SerializerSettings. Using (slow) DataContractSerializer as default.");
#endif
SerializerSettings.valueSerializer = ObjectSerializer.Get<Value>();
}
values = new Record<Key, Value>[BufferSize][];
segmentOffsets = new long[SegmentBufferSize];
objectLogDevice = settings.ObjectLogDevice;
if ((settings.LogDevice as NullDevice == null) && (KeyHasObjects() || ValueHasObjects()))
{
if (objectLogDevice == null)
throw new FasterException("Objects in key/value, but object log not provided during creation of FASTER instance");
if (objectLogDevice.SegmentSize != -1)
throw new FasterException("Object log device should not have fixed segment size. Set preallocateFile to false when calling CreateLogDevice for object log");
}
}
internal override int OverflowPageCount => overflowPagePool.Count;
public override void Reset()
{
base.Reset();
objectLogDevice.Reset();
for (int index = 0; index < BufferSize; index++)
{
ReturnPage(index);
}
Array.Clear(segmentOffsets, 0, segmentOffsets.Length);
Initialize();View on GitHub (pinned to 321d872eab)