{"record":{"id":"e6c777e5a7e8b7a9","repo":"microsoft/FASTER","slug":"max-length-of-iterator-name-is-20-characters","errorCode":null,"errorMessage":"Max length of iterator name is 20 characters","messagePattern":"Max length of iterator name is 20 characters","errorType":"exception","errorClass":"FasterException","httpStatus":null,"severity":"error","filePath":"cs/src/core/FasterLog/FasterLog.cs","lineNumber":1835,"sourceCode":"                if (name != null)\n                    throw new FasterException(\"Cannot use named iterators with read-only FasterLog\");\n                if (scanUncommitted)\n                    throw new FasterException(\"Cannot use scanUncommitted with read-only FasterLog\");\n            }\n\n            if (scanUncommitted && !AutoRefreshSafeTailAddress)\n                throw new FasterException(\"Cannot use scanUncommitted without setting AutoRefreshSafeTailAddress to true in FasterLog settings\");\n\n            FasterLogScanIterator iter;\n            if (recover && name != null && RecoveredIterators != null && RecoveredIterators.ContainsKey(name))\n                iter = new FasterLogScanIterator(this, allocator, RecoveredIterators[name], endAddress, getMemory, scanBufferingMode, epoch, headerSize, name, scanUncommitted, logger: logger);\n            else\n                iter = new FasterLogScanIterator(this, allocator, beginAddress, endAddress, getMemory, scanBufferingMode, epoch, headerSize, name, scanUncommitted, logger: logger);\n\n            if (name != null)\n            {\n                if (name.Length > 20)\n                    throw new FasterException(\"Max length of iterator name is 20 characters\");\n                if (PersistedIterators.ContainsKey(name))\n                    logger?.LogDebug(\"Iterator name exists, overwriting\");\n                PersistedIterators[name] = iter;\n            }\n\n            if (Interlocked.Increment(ref logRefCount) == 1)\n                throw new FasterException(\"Cannot scan disposed log instance\");\n            return iter;\n        }\n\n        /// <summary>\n        /// Random read record from log, at given address\n        /// </summary>\n        /// <param name=\"address\">Logical address to read from</param>\n        /// <param name=\"estimatedLength\">Estimated length of entry, if known</param>\n        /// <param name=\"token\">Cancellation token</param>\n        /// <returns></returns>\n        public async ValueTask<(byte[], int)> ReadAsync(long address, int estimatedLength = 0, CancellationToken token = default)","sourceCodeStart":1817,"sourceCodeEnd":1853,"githubUrl":"https://github.com/microsoft/FASTER/blob/321d872eabda6a0345c8bd76419f89723ed864ae/cs/src/core/FasterLog/FasterLog.cs#L1817-L1853","documentation":"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.","triggerScenarios":"Calling FasterLog.Scan(..., name: \"a-name-longer-than-20-characters\", recover: true) with a name whose Length > 20.","commonSituations":"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.","solutions":["Shorten the iterator name to 20 characters or fewer (e.g. a hash or truncated prefix).","Use a short name and map it to a longer logical description in your own configuration.","If you need unique long identifiers, store a 20-char key (e.g. base64/hash of the full name) in PersistedIterators."],"exampleFix":"// before\nvar iter = log.Scan(0, long.MaxValue, name: \"order-events-consumer-group-1\", recover: true);\n// after\nvar iter = log.Scan(0, long.MaxValue, name: \"orders-cg-1\", recover: true);","handlingStrategy":"validation","validationCode":"if (iteratorName?.Length > 20)\n    throw new ArgumentException(\"FasterLog iterator name must be <= 20 characters\", nameof(iteratorName));","typeGuard":null,"tryCatchPattern":"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 */ }","preventionTips":["Generate persisted iterator names from short hashes (e.g. 16-char hex) instead of descriptive strings.","Validate names at configuration load time, before constructing the log.","Define a name factory that enforces the 20-char limit."],"tags":["fasterlog","iterator","validation","csharp"],"backgroundTag":"invalid-argument-value","analyzedSha":"321d872eabda6a0345c8bd76419f89723ed864ae","analyzedAt":"2026-09-15T22:18:00.693Z","contentChangedAt":"2026-09-15T22:18:00.693Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}