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

  1. Identify which build wrote the data and which is reading it; align them.
  2. Migrate legacy custom-object data via RESP-level export/import rather than reusing raw object files.
  3. 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

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


AI-assisted analysis of microsoft/garnet@951b0fc683 (2026-08-13). Data as JSON: /api/errors/f9d856389b58da4b. Report an issue: GitHub.