microsoft/FASTER · error · FasterException

Invalid Enum Argument

Error message

Invalid Enum Argument

What it means

IndexResizeStateMachine.GlobalBeforeEnteringState switches on the current Phase to prepare the system before entering the next state during an index resize. Any Phase value outside the handled cases (PREPARE_GROW, IN_PROGRESS_GROW, WAIT, REST, etc.) falls into the default branch, which throws this exception. It is an internal exhaustive-switch guard, not a user input validation error.

Solutions

  1. Ensure no checkpoint or version change operation is running concurrently with ResizeIndex; serialize index maintenance operations.
  2. Restart the process and retry the resize from a clean REST phase state.
  3. If reproducible, file a bug with the phase value and operation trace - this indicates an internal state machine violation.

Example fix

// before
await faster.TakeCheckpointAsync();
faster.ResizeIndex(newSize); // concurrent ops may corrupt phase transitions
// after
await faster.TakeCheckpointAsync(); // await completion first
await faster.ResizeIndexAsync(newSize); // run resize exclusively
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure no other state-machine op is active before resizing
if (Interlocked.CompareExchange(ref resizeInProgress, 1, 0) != 0)
    throw new InvalidOperationException("Another index maintenance operation is in progress.");

Try / catch

try
{
    faster.ResizeIndex(newSize);
}
catch (FasterException ex) when (ex.Message == "Invalid Enum Argument")
{
    logger.LogError(ex, "Index resize state machine corrupted; restart required");
    throw;
}

Prevention

When it happens

Trigger: An internal state-machine corruption during an index resize: a phase value that the resize state machine never expects, typically due to a concurrent checkpoint/resize collision or a bug in phase transitions, not direct API misuse.

Common situations: Calling ResizeIndex while a version change or snapshot is in flight; resuming a resize after an unclean crash left resizeInfo in an unexpected phase; concurrent ResizeIndex calls.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of microsoft/FASTER@321d872eab (2026-09-15). Data as JSON: /api/errors/6b43b0c75f8b19b9. Report an issue: GitHub.

Appendix: source

Thrown at cs/src/core/Index/Synchronization/IndexResizeStateMachine.cs:44

                    break;
                case Phase.IN_PROGRESS_GROW:
                    // Set up the transition to new version of HT
                    var numChunks = (int) (faster.state[faster.resizeInfo.version].size / Constants.kSizeofChunk);
                    if (numChunks == 0) numChunks = 1; // at least one chunk

                    faster.numPendingChunksToBeSplit = numChunks;
                    faster.splitStatus = new long[numChunks];
                    faster.overflowBucketsAllocatorResize = faster.overflowBucketsAllocator;
                    faster.overflowBucketsAllocator = new MallocFixedPageSize<HashBucket>();
                    faster.Initialize(1 - faster.resizeInfo.version, faster.state[faster.resizeInfo.version].size * 2, faster.sectorSize);

                    faster.resizeInfo.version = 1 - faster.resizeInfo.version;
                    break;
                case Phase.REST:
                    // nothing to do
                    break;
                default:
                    throw new FasterException("Invalid Enum Argument");
            }
        }

        /// <inheritdoc />
        public void GlobalAfterEnteringState<Key, Value>(
            SystemState next,
            FasterKV<Key, Value> faster)
        {
            switch (next.Phase)
            {
                case Phase.PREPARE_GROW:
                    bool isProtected = faster.epoch.ThisInstanceProtected();
                    if (!isProtected)
                        faster.epoch.Resume();
                    try
                    {
                        faster.epoch.BumpCurrentEpoch(() => allThreadsInPrepareGrow = true);
                    }

View on GitHub (pinned to 321d872eab)