microsoft/garnet · critical · Exception

invalid metadata length: {hlri.cookie.Length} < 4

Error message

invalid metadata length: {hlri.cookie.Length} < 4

What it means

Thrown during legacy single-log checkpoint cookie deserialization when the cookie byte buffer is shorter than 4 bytes, too small to read the leading int cookieSize. This indicates a truncated, corrupt, or incompatible checkpoint metadata blob. The code runs in an unsafe fixed block reading primitive sizes directly from the buffer.

Source

Thrown at libs/cluster/Server/Replication/GarnetClusterCheckpointManager.cs:121

        /// Retrieve RecoveredSafeAofAddress and RecoveredReplicationId for checkpoint
        /// </summary>
        /// <param name="logToken"></param>
        /// <param name="recoveredSafeAofAddress"></param>
        /// <param name="recoveredReplicationId"></param>
        /// <exception cref="Exception"></exception>
        public unsafe void GetCheckpointCookieMetadata(Guid logToken, ref AofAddress recoveredSafeAofAddress, out string recoveredReplicationId)
        {
            var metadata = GetLogCheckpointMetadata(logToken);
            var hlri = ConvertMetadata(metadata);

            recoveredReplicationId = null;
            if (RecoveredSafeAofAddress.Length == 1)
            {
                // Legacy single log deserialization for backward compatibility
                var bytesRead = sizeof(int);
                fixed (byte* ptr = hlri.cookie)
                {
                    if (hlri.cookie.Length < 4) throw new Exception($"invalid metadata length: {hlri.cookie.Length} < 4");
                    var cookieSize = *(int*)ptr;
                    bytesRead += cookieSize;

                    if (hlri.cookie.Length < 12) throw new Exception($"invalid metadata length: {hlri.cookie.Length} < 12");
                    recoveredSafeAofAddress[0] = *(long*)(ptr + 4);

                    if (hlri.cookie.Length < 52) throw new Exception($"invalid metadata length: {hlri.cookie.Length} < 52");
                    recoveredReplicationId = Encoding.ASCII.GetString(ptr + 12, 40);
                }
            }
            else
            {
                // Multi-log cookie
                using var ms = new MemoryStream(hlri.cookie);
                using var reader = new BinaryReader(ms, Encoding.ASCII);
                recoveredReplicationId = reader.ReadInt32() > 0 ? reader.ReadString() : null;
                recoveredSafeAofAddress = AofAddress.Deserialize(reader);
                reader.Dispose();

View on GitHub (pinned to 951b0fc683)

Solutions

  1. Restore from a known-good full checkpoint instead of the corrupt one.
  2. Verify checkpoint file integrity and version compatibility before recovery.
  3. If upgrading across versions that changed the cookie format, take a fresh full checkpoint after upgrade.
Defensive patterns

Strategy: validation

Validate before calling

// Validate cookie length before unsafe reads
if (hlri.cookie == null || hlri.cookie.Length < 4)
    throw new InvalidDataException($"Checkpoint cookie too short ({hlri?.cookie?.Length ?? -1} bytes); checkpoint may be corrupt or from an incompatible version");

Try / catch

try { manager.GetCheckpointCookieMetadata(logToken, ref addr, out var id); }
catch (Exception ex) when (ex.Message.Contains("invalid metadata length"))
{
    logger?.LogError(ex, "Corrupt/incompatible checkpoint cookie for log {logToken}; recovering from a full checkpoint instead", logToken);
    // fall back to a known-good full checkpoint
}

Prevention

When it happens

Trigger: GetCheckpointCookieMetadata on a checkpoint whose embedded cookie is < 4 bytes — a malformed or partially-written checkpoint recovered from an older/incompatible version.

Common situations: Recovering a checkpoint from an incompatible Garnet version that wrote a differently-shaped cookie; a checkpoint file truncated by a crash mid-write; manual corruption of checkpoint metadata files on disk.

Related errors


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