{"record":{"id":"9227b4e924de989c","repo":"microsoft/garnet","slug":"cannot-cast-a-disklogrecord-to-a-memory-logrecord","errorCode":null,"errorMessage":"Cannot cast a DiskLogRecord to a memory LogRecord.","messagePattern":"Cannot cast a DiskLogRecord to a memory LogRecord\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"libs/storage/Tsavorite/cs/src/core/Allocator/SpanByteScanIterator.cs","lineNumber":406,"sourceCode":"        }\n\n        /// <inheritdoc/>\n        public SpanByteAndMemory ValueSpanByteAndMemory => diskLogRecord.ValueSpanByteAndMemory;\n\n        /// <inheritdoc/>\n        public long ETag => diskLogRecord.ETag;\n\n        /// <inheritdoc/>\n        public long Expiration => diskLogRecord.Expiration;\n\n        /// <inheritdoc/>\n        public void ClearValueIfHeap() { }  // Not relevant for \"iterator as logrecord\"\n\n        /// <inheritdoc/>\n        public bool IsMemoryLogRecord => false;\n\n        /// <inheritdoc/>\n        public unsafe ref LogRecord AsMemoryLogRecordRef() => throw new InvalidOperationException(\"Cannot cast a DiskLogRecord to a memory LogRecord.\");\n\n        /// <inheritdoc/>\n        public bool IsDiskLogRecord => true;\n\n        /// <inheritdoc/>\n        public unsafe ref DiskLogRecord AsDiskLogRecordRef() => ref Unsafe.AsRef(in diskLogRecord);\n\n        /// <inheritdoc/>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public RecordFieldInfo GetRecordFieldInfo() => diskLogRecord.GetRecordFieldInfo();\n\n        /// <inheritdoc/>\n        public int AllocatedSize => diskLogRecord.AllocatedSize;\n\n        /// <inheritdoc/>\n        public int ActualSize => diskLogRecord.ActualSize;\n\n        /// <inheritdoc/>","sourceCodeStart":388,"sourceCodeEnd":424,"githubUrl":"https://github.com/microsoft/garnet/blob/951b0fc6838721f89d102c2bbe1b914e8d39d700/libs/storage/Tsavorite/cs/src/core/Allocator/SpanByteScanIterator.cs#L388-L424","documentation":"The disk-backed SpanByteScanIterator record is a DiskLogRecord wrapper over pinned transient (on-device-read) memory with a different layout from an in-memory LogRecord. AsMemoryLogRecordRef throws InvalidOperationException to prevent unsafe reinterpretation of one as the other. IsMemoryLogRecord is false for these records.","triggerScenarios":"Calling AsMemoryLogRecordRef() on a record obtained from a disk scan iterator (where IsMemoryLogRecord is false and IsDiskLogRecord is true). Generic code over ISourceLogRecord that assumes every iterator record is a memory record.","commonSituations":"A generic helper written and tested against the in-memory scan path, later invoked on the disk-scan path; code that unconditionally calls AsMemoryLogRecordRef to access memory-only fields like PhysicalAddress.","solutions":["Branch on IsMemoryLogRecord / IsDiskLogRecord before calling either As-ref method.","Prefer the ISourceLogRecord interface accessors over casting to the concrete LogRecord/DiskLogRecord.","Where you must have a memory record, obtain it from a memory scan iterator rather than the disk iterator."],"exampleFix":"// before\nref LogRecord r = ref src.AsMemoryLogRecordRef();\n\n// after\nif (src.IsDiskLogRecord)\n{\n    ref DiskLogRecord d = ref src.AsDiskLogRecordRef();\n    // ... disk-specific access\n}\nelse\n{\n    ref LogRecord m = ref src.AsMemoryLogRecordRef();\n    // ... memory-specific access\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"static bool IsMemoryRecord<T>(in T src) where T : ISourceLogRecord => src.IsMemoryLogRecord;\n\nstatic bool IsDiskRecord<T>(in T src) where T : ISourceLogRecord => src.IsDiskLogRecord;","tryCatchPattern":null,"preventionTips":["Always check IsMemoryLogRecord/IsDiskLogRecord before calling either As-ref method.","Prefer ISourceLogRecord interface accessors over casting to concrete record types.","Test generic record helpers against both memory and disk scan iterators."],"tags":["tsavorite","record-type","scan","type-mismatch","disk"],"backgroundTag":null,"analyzedSha":"951b0fc6838721f89d102c2bbe1b914e8d39d700","analyzedAt":"2026-08-13T19:01:32.939Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}