microsoft/garnet · error · ArgumentException

recoveryPath is required.

Error message

recoveryPath is required.

What it means

Thrown by the static RecoverFromCprSnapshot when recoveryPath is null or empty. The native bftree_new_from_cpr_snapshot needs a source file path; an empty one is rejected early by the managed wrapper with an ArgumentException before any native call.

Source

Thrown at libs/native/bftree-garnet/BfTreeService.cs:557

                throw new InvalidOperationException("Failed to take CPR snapshot of BfTree.");
        }

        /// <summary>
        /// Recover a BfTree from a CPR snapshot file. Unified API for disk-backed and
        /// memory-backed (cache_only) trees — the storage backend is recorded in the
        /// snapshot and inferred by the native library.
        /// </summary>
        /// <param name="recoveryPath">Source CPR snapshot file path.</param>
        /// <param name="enableSnapshots">Enable CPR snapshot support on the recovered tree.
        /// Required if the recovered tree will be snapshotted later (flush/checkpoint/migration).</param>
        /// <param name="storageBackend">Storage backend of the recovered tree (for managed tracking).</param>
        public static BfTreeService RecoverFromCprSnapshot(
            string recoveryPath,
            bool enableSnapshots,
            StorageBackendType storageBackend)
        {
            if (string.IsNullOrEmpty(recoveryPath))
                throw new ArgumentException("recoveryPath is required.", nameof(recoveryPath));

            var recoveryBytes = Encoding.UTF8.GetBytes(recoveryPath);
            byte useSnapshot = (byte)(enableSnapshots ? 1 : 0);
            nint treePtr;
            fixed (byte* rp = recoveryBytes)
            {
                treePtr = NativeBfTreeMethods.bftree_new_from_cpr_snapshot(
                    rp, recoveryBytes.Length,
                    useSnapshot,
                    null, 0);
            }
            if (treePtr == 0)
                throw new InvalidOperationException($"Failed to recover BfTree from CPR snapshot '{recoveryPath}'.");
            return new BfTreeService(treePtr, storageBackend, filePath: null);
        }

        /// <summary>
        /// Drains scan iterator via callback — zero per-record allocation.

View on GitHub (pinned to 951b0fc683)

Solutions

  1. Persist the snapshot path durably so recovery can find it after restart.
  2. Validate !string.IsNullOrWhiteSpace(recoveryPath) before calling.
  3. If no snapshot exists, fall back to creating a fresh tree instead of recovering.
  4. Fail fast at startup with a clear config error if recovery is required but the path is unset.

Example fix

// before
var tree = BfTreeService.RecoverFromCprSnapshot(recoveryPath, enableSnapshots: true, backend);

// after
if (string.IsNullOrWhiteSpace(recoveryPath))
    throw new InvalidOperationException("No CPR snapshot path configured for recovery.");
var tree = BfTreeService.RecoverFromCprSnapshot(recoveryPath, enableSnapshots: true, backend);
Defensive patterns

Strategy: validation

Validate before calling

if (string.IsNullOrWhiteSpace(recoveryPath))
    throw new ArgumentException("recoveryPath is required.", nameof(recoveryPath));

Type guard

static bool HasRecoveryPath(string path) => !string.IsNullOrWhiteSpace(path);

Try / catch

try { tree = BfTreeService.RecoverFromCprSnapshot(recoveryPath, true, backend); }
catch (ArgumentException ex) when (ex.ParamName == nameof(recoveryPath)) { tree = CreateFreshTree(); }

Prevention

When it happens

Trigger: Calling RecoverFromCprSnapshot(null, ...) or RecoverFromCprSnapshot("", ...) — typically when the recovery source path was not supplied (e.g. a restart where the last snapshot path was not persisted, or a migration step that omitted the source).

Common situations: Startup recovery where the snapshot path is read from an unset environment variable or config key; a test that forgets to pass the snapshot path; a failover routine that has no recorded snapshot location.

Related errors


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