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

  1. Assign LogSettings.ObjectLogDevice = Devices.CreateLogDevice("objectlog.log", preallocateFile: false).
  2. If objects should stay in memory only, make both LogDevice and ObjectLogDevice NullDevice instances.
  3. 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

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


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)