microsoft/FASTER · error · FasterException

Session named already exists in recovery info, use…

Error message

Session named {sessionName} already exists in recovery info, use RecoverSession to resume it

What it means

FASTER tracks sessions that exist in checkpoint/recovery info by name. When NewSession is called with a sessionName that already appears in _recoveredSessionNameMap, the library refuses to create a duplicate because that name must be resumed with RecoverSession/ResumeSession instead of created fresh.

Solutions

  1. Call fht.RecoverSession(sessionName) (or ResumeSession) instead of NewSession to resume the recovered session.
  2. Use a unique new sessionName for NewSession calls.
  3. Pass null as sessionName to let FASTER auto-generate an unnamed session if recovery-by-name is not needed.

Example fix

// before
var session = fht.NewSession<Functions>(functions, sessionName: "worker1");
// after
var session = fht.RecoverSession<Functions>(functions, sessionName: "worker1", out CommitPoint cp);
Defensive patterns

Strategy: validation

Validate before calling

fht.Recover(); // ensure recovery info is loaded
if (recoveredSessionNames.Contains(sessionName))
    session = fht.RecoverSession<Functions>(functions, sessionName, out var cp);
else
    session = fht.NewSession<Functions>(functions, sessionName);

Prevention

When it happens

Trigger: Calling fht.NewSession<...>(functions, sessionName: "mySession") where "mySession" was previously checkpointed (exists in _recoveredSessionNameMap), instead of calling RecoverSession.

Common situations: Reopening a FASTER instance from checkpoints after a restart and blindly creating sessions with the same names used before the checkpoint; session-name collisions after failover recovery.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


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

Appendix: source

Thrown at cs/src/core/ClientSession/FASTERClientSession.cs:170

        /// <returns>Session instance</returns>
        internal ClientSession<Key, Value, Input, Output, Context, Functions> NewSession<Input, Output, Context, Functions>(Functions functions, string sessionName = null,
                SessionVariableLengthStructSettings<Value, Input> sessionVariableLengthStructSettings = null, ReadCopyOptions readCopyOptions = default)
            where Functions : IFunctions<Key, Value, Input, Output, Context>
            => InternalNewSession<Input, Output, Context, Functions, ClientSession<Key, Value, Input, Output, Context, Functions>>(functions, sessionName,
                            ctx => new ClientSession<Key, Value, Input, Output, Context, Functions>(this, ctx, functions, sessionVariableLengthStructSettings), readCopyOptions);

        private TSession InternalNewSession<Input, Output, Context, Functions, TSession>(Functions functions, string sessionName,
                                                                            Func<FasterExecutionContext<Input, Output, Context>, TSession> sessionCreator, ReadCopyOptions readCopyOptions)
            where TSession : IClientSession
        {
            if (functions == null)
                throw new ArgumentNullException(nameof(functions));

            if (sessionName == "")
                throw new FasterException("Cannot use empty string as session name");

            if (sessionName != null && _recoveredSessionNameMap != null && _recoveredSessionNameMap.ContainsKey(sessionName))
                throw new FasterException($"Session named {sessionName} already exists in recovery info, use RecoverSession to resume it");

            int sessionID = Interlocked.Increment(ref maxSessionID);
            var ctx = new FasterExecutionContext<Input, Output, Context>();
            InitContext(ctx, sessionID, sessionName);
            ctx.MergeReadCopyOptions(this.ReadCopyOptions, readCopyOptions);
            var prevCtx = new FasterExecutionContext<Input, Output, Context>();
            InitContext(prevCtx, sessionID, sessionName);
            prevCtx.version--;
            prevCtx.ReadCopyOptions = ctx.ReadCopyOptions;

            ctx.prevCtx = prevCtx;

            if (_activeSessions == null)
                Interlocked.CompareExchange(ref _activeSessions, new Dictionary<int, SessionInfo>(), null);

            var session = sessionCreator(ctx);
            lock (_activeSessions)
                _activeSessions.Add(sessionID, new SessionInfo { sessionName = sessionName, session = session, isActive = true });

View on GitHub (pinned to 321d872eab)