microsoft/FASTER · error · FasterException
Invalid compaction type
Error message
Invalid compaction type
What it means
Compact dispatches on the CompactionType enum; only CompactionType.Scan and CompactionType.Lookup are implemented. Any other value (invalid cast, uninitialized enum, future enum member from a newer library) hits the default arm and throws.
Solutions
- Pass CompactionType.Scan or CompactionType.Lookup explicitly.
- Validate any deserialized/configured CompactionType before calling Compact.
- Upgrade the FASTER package if the value comes from a newer version's enum.
Example fix
// before
var type = (CompactionType)readFromConfig;
fht.Compact<Input, Output, Context, Functions, MyCompactionFunctions>(functions, cf, type, ref input, ref output, untilAddress);
// after
if (type is not (CompactionType.Scan or CompactionType.Lookup))
throw new InvalidOperationException($"Unsupported compaction type: {type}"); Defensive patterns
Strategy: validation
Validate before calling
if (compactionType is not (CompactionType.Scan or CompactionType.Lookup))
throw new ArgumentOutOfRangeException(nameof(compactionType), compactionType, "Unsupported compaction type"); Type guard
static bool IsValidCompactionType(CompactionType t) => t is CompactionType.Scan or CompactionType.Lookup;
Try / catch
try { fht.Compact<...>(...); }
catch (FasterException ex) when (ex.Message == "Invalid compaction type") { /* fix enum source */ } Prevention
- Never cast arbitrary integers to CompactionType; use the enum members directly.
- Validate enum values deserialized from config or storage.
- Pin the FASTER package version if persisting enum values.
When it happens
Trigger: Calling fht.Compact<...>((CompactionType)99, ...) with a value outside the Scan/Lookup members of CompactionType.
Common situations: Loading an enum value from config/persistence that maps to no valid member; code written against a newer FASTER version with extra compaction types running on an older assembly.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Can compact only until Log.SafeReadOnlyAddress
- Out of order message within session
- Unexpected status of SubscribeKV
- Cannot use BlittableParameterSerializer with non-blittable…
- The inner list is full!
AI-assisted analysis of microsoft/FASTER@321d872eab (2026-09-15).
Data as JSON: /api/errors/0d2c9c88d196b31f.
Report an issue: GitHub.
Appendix: source
Thrown at cs/src/core/Compaction/FASTERCompaction.cs:31
/// is not deleted from disk. Caller is responsible for truncating the physical log on disk by taking a checkpoint or calling Log.Truncate
/// </summary>
/// <param name="functions">Functions used to manage key-values during compaction</param>
/// <param name="cf">User provided compaction functions (see <see cref="ICompactionFunctions{Key, Value}"/>).</param>
/// <param name="input">Input for SingleWriter</param>
/// <param name="output">Output from SingleWriter; it will be called all records that are moved, before Compact() returns, so the user must supply buffering or process each output completely</param>
/// <param name="untilAddress">Compact log until this address</param>
/// <param name="compactionType">Compaction type (whether we lookup records or scan log for liveness checking)</param>
/// <param name="sessionVariableLengthStructSettings">Session variable length struct settings</param>
/// <returns>Address until which compaction was done</returns>
internal long Compact<Input, Output, Context, Functions, CompactionFunctions>(Functions functions, CompactionFunctions cf, ref Input input, ref Output output, long untilAddress, CompactionType compactionType, SessionVariableLengthStructSettings<Value, Input> sessionVariableLengthStructSettings = null)
where Functions : IFunctions<Key, Value, Input, Output, Context>
where CompactionFunctions : ICompactionFunctions<Key, Value>
{
return compactionType switch
{
CompactionType.Scan => CompactScan<Input, Output, Context, Functions, CompactionFunctions>(functions, cf, ref input, ref output, untilAddress, sessionVariableLengthStructSettings),
CompactionType.Lookup => CompactLookup<Input, Output, Context, Functions, CompactionFunctions>(functions, cf, ref input, ref output, untilAddress, sessionVariableLengthStructSettings),
_ => throw new FasterException("Invalid compaction type"),
};
}
private long CompactLookup<Input, Output, Context, Functions, CompactionFunctions>(Functions functions, CompactionFunctions cf, ref Input input, ref Output output, long untilAddress, SessionVariableLengthStructSettings<Value, Input> sessionVariableLengthStructSettings)
where Functions : IFunctions<Key, Value, Input, Output, Context>
where CompactionFunctions : ICompactionFunctions<Key, Value>
{
if (untilAddress > hlog.SafeReadOnlyAddress)
throw new FasterException("Can compact only until Log.SafeReadOnlyAddress");
var lf = new LogCompactionFunctions<Key, Value, Input, Output, Context, Functions>(functions);
using var fhtSession = For(lf).NewSession<LogCompactionFunctions<Key, Value, Input, Output, Context, Functions>>(sessionVariableLengthStructSettings: sessionVariableLengthStructSettings);
using (var iter1 = Log.Scan(Log.BeginAddress, untilAddress))
{
long numPending = 0;
while (iter1.GetNext(out var recordInfo))
{View on GitHub (pinned to 321d872eab)