microsoft/FASTER · error · FasterException

Max length of iterator name is 20 characters

Error message

Max length of iterator name is 20 characters

What it means

Named (persisted) iterator names are limited to 20 characters because the name is stored inline in persisted iterator metadata. FasterLog.ValidateName checks this after creating the scan iterator in FasterLog.cs:1835 and throws FasterException when exceeded.

Solutions

  1. Shorten the iterator name to 20 characters or fewer (e.g. a hash or truncated prefix).
  2. Use a short name and map it to a longer logical description in your own configuration.
  3. If you need unique long identifiers, store a 20-char key (e.g. base64/hash of the full name) in PersistedIterators.

Example fix

// before
var iter = log.Scan(0, long.MaxValue, name: "order-events-consumer-group-1", recover: true);
// after
var iter = log.Scan(0, long.MaxValue, name: "orders-cg-1", recover: true);
Defensive patterns

Strategy: validation

Validate before calling

if (iteratorName?.Length > 20)
    throw new ArgumentException("FasterLog iterator name must be <= 20 characters", nameof(iteratorName));

Try / catch

try { var iter = log.Scan(0, long.MaxValue, name: name, recover: true); } catch (FasterException ex) when (ex.Message.Contains("Max length of iterator name")) { /* shorten name and retry */ }

Prevention

When it happens

Trigger: Calling FasterLog.Scan(..., name: "a-name-longer-than-20-characters", recover: true) with a name whose Length > 20.

Common situations: Developers use descriptive iterator names like "subscription-processor-west" or GUID strings (36 chars) for durable iterators that must survive restarts, exceeding the fixed 20-char limit.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at cs/src/core/FasterLog/FasterLog.cs:1835

                if (name != null)
                    throw new FasterException("Cannot use named iterators with read-only FasterLog");
                if (scanUncommitted)
                    throw new FasterException("Cannot use scanUncommitted with read-only FasterLog");
            }

            if (scanUncommitted && !AutoRefreshSafeTailAddress)
                throw new FasterException("Cannot use scanUncommitted without setting AutoRefreshSafeTailAddress to true in FasterLog settings");

            FasterLogScanIterator iter;
            if (recover && name != null && RecoveredIterators != null && RecoveredIterators.ContainsKey(name))
                iter = new FasterLogScanIterator(this, allocator, RecoveredIterators[name], endAddress, getMemory, scanBufferingMode, epoch, headerSize, name, scanUncommitted, logger: logger);
            else
                iter = new FasterLogScanIterator(this, allocator, beginAddress, endAddress, getMemory, scanBufferingMode, epoch, headerSize, name, scanUncommitted, logger: logger);

            if (name != null)
            {
                if (name.Length > 20)
                    throw new FasterException("Max length of iterator name is 20 characters");
                if (PersistedIterators.ContainsKey(name))
                    logger?.LogDebug("Iterator name exists, overwriting");
                PersistedIterators[name] = iter;
            }

            if (Interlocked.Increment(ref logRefCount) == 1)
                throw new FasterException("Cannot scan disposed log instance");
            return iter;
        }

        /// <summary>
        /// Random read record from log, at given address
        /// </summary>
        /// <param name="address">Logical address to read from</param>
        /// <param name="estimatedLength">Estimated length of entry, if known</param>
        /// <param name="token">Cancellation token</param>
        /// <returns></returns>
        public async ValueTask<(byte[], int)> ReadAsync(long address, int estimatedLength = 0, CancellationToken token = default)

View on GitHub (pinned to 321d872eab)