microsoft/FASTER · error · FasterException

This method can only be used with a read-only FasterLog…

Error message

This method can only be used with a read-only FasterLog instance used for iteration. Set FasterLogSettings.ReadOnlyMode to true during creation to indicate this.

What it means

RecoverReadOnly() synchronously advances a log instance to the latest valid commit, but this is only meaningful for instances created in read-only mode. FasterLog checks readOnlyMode at FasterLog.cs:2209 and throws if the instance is a normal (writable) log.

Solutions

  1. Set FasterLogSettings.ReadOnlyMode = true when constructing the instance used for iteration.
  2. Use a separate read-only FasterLog instance for recovery/iteration instead of the writable producer instance.
  3. On a writable log, recovery happens automatically at construction or via commit APIs; remove the RecoverReadOnly call.

Example fix

// before
var log = new FasterLog(new FasterLogSettings { LogDevice = sharedDevice });
log.RecoverReadOnly();
// after
var log = new FasterLog(new FasterLogSettings { LogDevice = sharedDevice, ReadOnlyMode = true });
log.RecoverReadOnly();
Defensive patterns

Strategy: validation

Validate before calling

// caller-side guard
if (!logSettings.ReadOnlyMode)
    throw new InvalidOperationException("RecoverReadOnly requires FasterLogSettings.ReadOnlyMode = true");

Try / catch

try { log.RecoverReadOnly(); } catch (FasterException ex) when (ex.Message.Contains("read-only FasterLog instance")) { /* use a read-only instance */ }

Prevention

When it happens

Trigger: Calling FasterLog.RecoverReadOnly() on an instance created without FasterLogSettings.ReadOnlyMode = true.

Common situations: Developers replicating the read-only replication pattern (a follower tailing a shared log device) forget to set ReadOnlyMode in settings, then call RecoverReadOnly in their polling loop; often after copying code from the read-only FasterLog sample.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

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

            foreach (var item in _lastPersistedIterators)
            {
                if (info.Iterators.TryGetValue(item.Key, out var other))
                {
                    if (item.Value != other) return true;
                }
                else
                    return true;
            }
            return false;
        }

        /// <summary>
        /// Synchronously recover instance to FasterLog's latest valid commit, when being used as a readonly log iterator
        /// </summary>
        public void RecoverReadOnly()
        {
            if (!readOnlyMode)
                throw new FasterException("This method can only be used with a read-only FasterLog instance used for iteration. Set FasterLogSettings.ReadOnlyMode to true during creation to indicate this.");

            RestoreLatest(out _, out _);
            SignalWaitingROIterators();
        }

        /// <summary>
        /// Asynchronously recover instance to FasterLog's latest commit, when being used as a readonly log iterator
        /// </summary>
        public async ValueTask RecoverReadOnlyAsync(CancellationToken cancellationToken = default)
        {
            if (!readOnlyMode)
                throw new FasterException("This method can only be used with a read-only FasterLog instance used for iteration. Set FasterLogSettings.ReadOnlyMode to true during creation to indicate this.");

            await RestoreLatestAsync(cancellationToken).ConfigureAwait(false);
            SignalWaitingROIterators();
        }

        private void SignalWaitingROIterators()

View on GitHub (pinned to 321d872eab)