{"record":{"id":"56020ab13aa109fe","repo":"microsoft/FASTER","slug":"cannot-recover-from","errorCode":null,"errorMessage":"Cannot recover from (","messagePattern":"Cannot recover from \\(","errorType":"exception","errorClass":"FasterException","httpStatus":null,"severity":"critical","filePath":"cs/src/core/Index/Recovery/Recovery.cs","lineNumber":397,"sourceCode":"                    recoveredICInfo.Recover(indexToken, checkpointManager);\n                    recoveredICInfo.info.DebugPrint(logger);\n                }\n            }\n            catch\n            {\n                recoveredICInfo = default;\n            }\n\n            if (recoveredICInfo.IsDefault())\n            {\n                logger?.LogInformation(\"Invalid index checkpoint token, recovering from beginning of log\");\n            }\n            else\n            {\n                // Check if the two checkpoints are compatible for recovery\n                if (!IsCompatible(recoveredICInfo.info, recoveredHLCInfo.info))\n                {\n                    throw new FasterException(\"Cannot recover from (\" + indexToken.ToString() + \",\" + hybridLogToken.ToString() + \") checkpoint pair!\\n\");\n                }\n            }\n        }\n\n        /// <inheritdoc />\n        public void Reset()\n        {\n            // Reset the hash index\n            Array.Clear(state[resizeInfo.version].tableRaw, 0, state[resizeInfo.version].tableRaw.Length);\n            overflowBucketsAllocator.Dispose();\n            overflowBucketsAllocator = new MallocFixedPageSize<HashBucket>();\n\n            // Reset the hybrid log\n            hlog.Reset();\n        }\n\n\n        private long InternalRecover(IndexCheckpointInfo recoveredICInfo, HybridLogCheckpointInfo recoveredHLCInfo, int numPagesToPreload, bool undoNextVersion, long recoverTo)","sourceCodeStart":379,"sourceCodeEnd":415,"githubUrl":"https://github.com/microsoft/FASTER/blob/321d872eabda6a0345c8bd76419f89723ed864ae/cs/src/core/Index/Recovery/Recovery.cs#L379-L415","documentation":"GetRecoveryInfo validates that the index checkpoint and hybrid log checkpoint form a compatible pair via IsCompatible before recovery proceeds. When the two Guid tokens come from different checkpoint sessions (their internal checkpoint metadata do not match), recovery cannot combine them and this exception is thrown. It guards against assembling a corrupted logical state from unrelated snapshots.","triggerScenarios":"Calling Recover(indexToken, hybridLogToken) with tokens taken at different times or from different FASTER instances, or manually specifying one token from an old checkpoint and another from a newer one.","commonSituations":"Persisting index and hybrid log tokens separately (e.g. in different config stores) and one being updated while the other was not; copying checkpoint directories selectively; testing with mixed tokens from multiple runs.","solutions":["Always pass the index and hybrid log tokens captured together from the same TakeFullCheckpoint/TakeIndexCheckpoint+TakeHybridLogCheckpoint call.","Use the secondary checkpoint API (Recover with a single token / checkpoint entry) so both tokens are resolved from one checkpoint entry.","Verify the checkpoint directory contents: both index and hybrid log checkpoint metadata for the pair must exist and come from the same session.","Retake a full checkpoint to obtain a fresh consistent token pair."],"exampleFix":"// before\nfaster.Recover(oldIndexToken, newHybridLogToken); // tokens from different sessions\n// after\nvar token = await faster.TakeFullCheckpointAsync(); // capture both tokens together\nSaveBothTokens(token.indexToken, token.hlogToken);\nfaster.Recover(token.indexToken, token.hlogToken);","handlingStrategy":"validation","validationCode":"// Persist and read index + hybrid log tokens as one atomic record\nvar (indexToken, hlogToken) = LoadTokenPair(); // always saved together at checkpoint time\nif (indexToken == Guid.Empty || hlogToken == Guid.Empty)\n    throw new InvalidOperationException(\"Incomplete token pair; retake checkpoint.\");\nfaster.Recover(indexToken, hlogToken);","typeGuard":null,"tryCatchPattern":"try\n{\n    faster.Recover(indexToken, hybridLogToken);\n}\ncatch (FasterException ex) when (ex.Message.StartsWith(\"Cannot recover from (\"))\n{\n    logger.LogError(\"Incompatible checkpoint pair {A}/{B}; falling back to latest checkpoint\", indexToken, hybridLogToken);\n    faster.Recover();\n}","preventionTips":["Store index and hybrid log tokens together in one transactional record.","Use TakeFullCheckpoint so a single call yields a consistent pair.","Never hand-copy tokens between environments or runs."],"tags":["faster","recovery","checkpoint","incompatible"],"backgroundTag":"incompatible-source-type","analyzedSha":"321d872eabda6a0345c8bd76419f89723ed864ae","analyzedAt":"2026-09-15T22:18:00.693Z","contentChangedAt":"2026-09-15T22:18:00.693Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}