microsoft/garnet · critical · GarnetException
Unsupported object type id 0x{type:X2}; the data may have be
Error message
Unsupported object type id 0x{type:X2}; the data may have been written by an incompatible Garnet version (e.g. legacy custom objects that used a different type-id range). What it means
Thrown by CustomDeserialize when a custom object's persisted type id falls below CustomCommandManager.CustomTypeIdStartOffset - i.e., in the reserved built-in band - yet is not a recognized built-in type. Per the code comments, this happens with legacy custom objects whose ids were based at LastObjectType+1 (older scheme) instead of the current fixed base, or with a build whose built-in/custom bands differ. Failing fast prevents silent data loss (returning null would drop the record).
Source
Thrown at libs/server/Objects/Types/GarnetObjectSerializer.cs:84
GarnetObjectType.SortedSet => new SortedSetObject(binaryReader),
GarnetObjectType.List => new ListObject(binaryReader),
GarnetObjectType.Hash => new HashObject(binaryReader),
GarnetObjectType.Set => new SetObject(binaryReader),
_ => CustomDeserialize((byte)type, binaryReader),
};
return obj;
}
private IGarnetObject CustomDeserialize(byte type, BinaryReader binaryReader)
{
// Built-in type ids (0..LastObjectType) are handled by the caller. A type id below the
// fixed custom-object base therefore lies in the reserved built-in band and is not valid
// for this build: it was written either by an older build whose custom objects were based
// at LastObjectType+1 (rather than the fixed base), or by a newer build with additional
// built-in types. Fail fast instead of silently returning null, which would drop the
// record and lose data without any indication.
if (type < CustomCommandManager.CustomTypeIdStartOffset)
throw new GarnetException($"Unsupported object type id 0x{type:X2}; the data may have been written by an incompatible Garnet version (e.g. legacy custom objects that used a different type-id range).");
if (!customCommandManager.TryGetCustomObjectCommand(type, out var cmd)) return null;
return cmd.factory.Deserialize(type, binaryReader);
}
/// <inheritdoc />
public override void Serialize(IGarnetObject obj) => SerializeInternal(base.writer, obj);
/// <summary>Thread safe version of Serialize.</summary>
/// <param name="obj"></param>
/// <returns></returns>
public static void Serialize(IGarnetObject obj, out byte[] bytes)
{
Debug.Assert(obj != null);
using var ms = new MemoryStream();
using var binaryWriter = new BinaryWriter(ms, Encoding.UTF8);
SerializeInternal(binaryWriter, obj);View on GitHub (pinned to 951b0fc683)
Solutions
- Identify which build wrote the data and which is reading it; align them.
- Migrate legacy custom-object data via RESP-level export/import rather than reusing raw object files.
- Ensure the same modules (and thus the same custom-id assignments) are loaded on the reading node.
Defensive patterns
Strategy: validation
Validate before calling
// Reject persisted custom type ids outside the valid custom band before deserializing
if (type < CustomCommandManager.CustomTypeIdStartOffset)
throw new InvalidOperationException($"Refusing custom object with out-of-band type id 0x{type:X2}."); Try / catch
catch (GarnetException ex) when (ex.Message.Contains("Unsupported object type id")) {
logger.LogCritical("Legacy/incompatible custom-object id encountered; migrate data via RESP export/import.");
throw;
} Prevention
- Treat custom-object id bands as a persisted contract; do not change the base across versions.
- Load the same set of modules in the same order on all nodes sharing data.
When it happens
Trigger: Deserializing a persisted custom object whose type id is in the reserved built-in band because it was written by an older Garnet (legacy custom-id scheme) or an incompatible build with a different band layout.
Common situations: Upgrading Garnet across the version that changed custom-object id basing; loading data written by a much older build; mixing builds with different CustomTypeIdStartOffset.
Related errors
- Unsupported object serialization format marker 0x{firstByte:
- Incompatible ClusterConfig version: expected {ClusterConfigV
- invalid metadata length: {hlri.cookie.Length} < 4
- invalid metadata length: {hlri.cookie.Length} < 12
- AofSizeLimit cannot be enforced with disabled AOF!
AI-assisted analysis of microsoft/garnet@951b0fc683 (2026-08-13).
Data as JSON: /api/errors/f9d856389b58da4b.
Report an issue: GitHub.