{"record":{"id":"274fbd96df2be505","repo":"microsoft/garnet","slug":"inplacewriter-readonlyspan-byte-value-is-not-sup","errorCode":null,"errorMessage":"InPlaceWriter(ReadOnlySpan<byte> value) is not supported in this ISessionFunctions implementation","messagePattern":"InPlaceWriter\\(ReadOnlySpan<byte> value\\) is not supported in this ISessionFunctions implementation","errorType":"exception","errorClass":"NotImplementedException","httpStatus":null,"severity":"error","filePath":"libs/storage/Tsavorite/cs/src/core/ClientSession/NoOpSessionFunctions.cs","lineNumber":32,"sourceCode":"    /// <remarks>\n    /// Because this is used for copy operations, the <see cref=\"GetUpsertFieldInfo{TKey, TSourceLogRecord}(TKey, in TSourceLogRecord, ref TInput)\"/>,\n    /// <see cref=\"InitialWriter{TSourceLogRecord}(ref LogRecord, in RecordSizeInfo, ref TInput, in TSourceLogRecord, ref TOutput, ref UpsertInfo)\"/>, and\n    /// <see cref=\"InPlaceWriter{TSourceLogRecord}(ref LogRecord, ref TInput, in TSourceLogRecord, ref TOutput, ref UpsertInfo)\"/>, and\n    /// methods are implemented to allow for copy of log records via Upsert, but no other methods are implemented.\n    /// </remarks>\n    /// <typeparam name=\"TInput\"></typeparam>\n    /// <typeparam name=\"TOutput\"></typeparam>\n    /// <typeparam name=\"TContext\"></typeparam>\n    internal struct NoOpSessionFunctions<TInput, TOutput, TContext> : ISessionFunctions<TInput, TOutput, TContext>\n    {\n        public readonly bool InitialDeleter(ref LogRecord logRecord, ref DeleteInfo deleteInfo) => true;\n\n        public readonly void PostInitialDeleter(ref LogRecord logRecord, ref DeleteInfo deleteInfo) { }\n\n        public readonly bool InPlaceDeleter(ref LogRecord logRecord, ref DeleteInfo deleteInfo) => true;\n\n        public readonly bool InPlaceWriter(ref LogRecord logRecord, ref TInput input, ReadOnlySpan<byte> srcValue, ref TOutput output, ref UpsertInfo upsertInfo)\n            => throw new NotImplementedException(\"InPlaceWriter(ReadOnlySpan<byte> value) is not supported in this ISessionFunctions implementation\");\n\n        public readonly bool InPlaceWriter(ref LogRecord logRecord, ref TInput input, IHeapObject srcValue, ref TOutput output, ref UpsertInfo upsertInfo)\n            => throw new NotImplementedException(\"InPlaceWriter(IHeapObject value) is not supported in this ISessionFunctions implementation\");\n\n        public readonly bool InPlaceWriter<TSourceLogRecord>(ref LogRecord dstLogRecord, ref TInput input, in TSourceLogRecord inputLogRecord, ref TOutput output, ref UpsertInfo upsertInfo)\n            where TSourceLogRecord : ISourceLogRecord\n        {\n            // This includes ETag and Expiration\n            var sizeInfo = new RecordSizeInfo() { FieldInfo = GetUpsertFieldInfo(key: dstLogRecord, inputLogRecord, ref input) };\n            dstLogRecord.PopulateRecordSizeInfoForIPU(ref sizeInfo);\n            return dstLogRecord.TryCopyFrom(in inputLogRecord, in sizeInfo);\n        }\n\n        public readonly bool CopyUpdater<TSourceLogRecord>(in TSourceLogRecord srcLogRecord, ref LogRecord dstLogRecord, in RecordSizeInfo sizeInfo, ref TInput input, ref TOutput output, ref RMWInfo rmwInfo)\n            where TSourceLogRecord : ISourceLogRecord\n            => true;\n\n        public readonly bool PostCopyUpdater<TSourceLogRecord>(in TSourceLogRecord srcLogRecord, ref LogRecord dstLogRecord, in RecordSizeInfo sizeInfo, ref TInput input, ref TOutput output, ref RMWInfo rmwInfo)","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/microsoft/garnet/blob/951b0fc6838721f89d102c2bbe1b914e8d39d700/libs/storage/Tsavorite/cs/src/core/ClientSession/NoOpSessionFunctions.cs#L14-L50","documentation":"NoOpSessionFunctions is an internal struct used by Tsavorite during compaction, iteration, and other internal operations that manipulate LogRecords directly rather than going through user-supplied callback values. It only implements the ISourceLogRecord-based overloads of InPlaceWriter/InitialWriter (for copying log records byte-for-byte). The ReadOnlySpan<byte> and IHeapObject overloads of InPlaceWriter throw NotImplementedException because compaction never upserts a raw span or heap object value — it always copies from a source log record.","triggerScenarios":"Tsavorite's internal compaction or checkpoint code path calls InPlaceWriter(ref LogRecord, ref TInput, ReadOnlySpan<byte> srcValue, ...) on a session using NoOpSessionFunctions. This indicates the compaction pipeline routed an upsert through the span-value path instead of the record-copy path. Since NoOpSessionFunctions is internal, external users cannot construct it directly — this error surfaces from within Tsavorite's own code during compaction.","commonSituations":"A Tsavorite framework bug in the compaction/copy-forward logic that incorrectly dispatches to the span-based InPlaceWriter; a custom checkpoint or compaction hook that triggers an upsert with a raw value during a NoOp session; upgrading Tsavorite to a version with a regression in compaction dispatch.","solutions":["Report this as a Tsavorite framework bug — the compaction code path should never call the span-based InPlaceWriter on a NoOpSessionFunctions instance.","If using a custom session functions implementation, ensure all InPlaceWriter overloads are implemented, not just the ISourceLogRecord one.","Try disabling or adjusting compaction settings to see if the issue is data-dependent (e.g. record sizes that trigger a different copy path)."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// If you suspect compaction may trigger this, catch NotImplementedException\n// and log details to report as a framework bug\ntry\n{\n    store.Log.ShiftHeadAddressForCompaction(targetAddress);\n}\ncatch (NotImplementedException ex) when (ex.Message.Contains(\"InPlaceWriter\"))\n{\n    logger.LogCritical(\"Tsavorite compaction hit unsupported InPlaceWriter path: {Message}\", ex.Message);\n    throw;\n}","preventionTips":["Since NoOpSessionFunctions is internal and used by compaction, this error indicates a framework bug — report it upstream.","If implementing custom ISessionFunctions, implement ALL InPlaceWriter overloads, not just the ISourceLogRecord one.","Pin your Tsavorite version after verifying compaction works with your data shapes."],"tags":["tsavorite","compaction","session-functions","inplace-writer","not-implemented","internal","csharp"],"backgroundTag":null,"analyzedSha":"951b0fc6838721f89d102c2bbe1b914e8d39d700","analyzedAt":"2026-08-13T19:01:32.939Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}