clockworklabs/SpacetimeDB · error · InvalidOperationException

Unknown compression type

Error message

Unknown compression type

What it means

Every ServerMessage arriving over the websocket starts with one byte naming the compression algorithm (0=None, 1=Brotli, 2=Gzip). CompressionHelpers.DecompressDecodeMessage casts that byte to the CompressionAlgos enum and throws InvalidOperationException for any other value. The client's parse loop catches it, logs the exception, fails pending operations and disconnects — so the observable effect is a dropped connection.

Source

Thrown at sdks/csharp/src/CompressionHelpers.cs:64

        /// Ensures efficient decompression by reading the entire stream at once to avoid
        /// performance issues with certain stream implementations.
        /// Throws <see cref="InvalidOperationException"/> if an unknown compression type is encountered.
        /// </summary>
        /// <param name="bytes">The compressed and encoded server message as a byte array.</param>
        /// <returns>The deserialized <see cref="ServerMessage"/> object.</returns>
        internal static ServerMessage DecompressDecodeMessage(byte[] bytes)
        {
            using var stream = new MemoryStream(bytes);

            // The stream will never be empty. It will at least contain the compression algo.
            var compression = (CompressionAlgos)stream.ReadByte();
            // Conditionally decompress and decode.
            Stream decompressedStream = compression switch
            {
                CompressionAlgos.None => stream,
                CompressionAlgos.Brotli => BrotliReader(stream),
                CompressionAlgos.Gzip => GzipReader(stream),
                _ => throw new InvalidOperationException("Unknown compression type"),
            };

            // TODO: consider pooling these.
            // DO NOT TRY TO TAKE THIS OUT. The BrotliStream ReadByte() implementation allocates an array
            // PER BYTE READ. You have to do it all at once to avoid that problem.
            MemoryStream memoryStream = new MemoryStream();
            decompressedStream.CopyTo(memoryStream);
            memoryStream.Seek(0, SeekOrigin.Begin);
            return new ServerMessage.BSATN().Read(new BinaryReader(memoryStream));
        }

        /// <summary>
        /// Prepare to read a BsatnRowList.
        ///
        /// This could return an IEnumerable, but we return the reader and row count directly to avoid an allocation.
        /// It is legitimate to repeatedly call <c>IStructuralReadWrite.Read<T></c> <c>rowCount</c> times on the resulting
        /// BinaryReader:
        /// Our decoding infrastructure guarantees that reading a value consumes the correct number of bytes

View on GitHub (pinned to 524b4487d9)

Solutions

  1. Upgrade the C# SDK package to the release matching your server version
  2. As a workaround, reconnect with WithCompression(Compression.None) so a conformant server sends uncompressed messages (algo byte 0)
  3. If you feed raw bytes in tests, ensure the first byte is 0, 1 or 2 before injecting the message
  4. If SDK and server versions already match, capture the frame and report it as a SpacetimeDB bug

Example fix

// before
conn.OnMessageReceived(arbitraryBytes, DateTime.UtcNow); // fixture without algo byte

// after
var fixedBytes = new byte[] { (byte)CompressionAlgos.None }.Concat(arbitraryBytes).ToArray();
conn.OnMessageReceived(fixedBytes, DateTime.UtcNow);
Defensive patterns

Strategy: validation

Validate before calling

// When injecting raw frames (tests), verify the algo byte first:
bool FrameHasKnownCompression(byte[] frame) =>
    frame.Length > 0 && frame[0] is 0 or 1 or 2; // None, Brotli, Gzip

Prevention

When it happens

Trigger: A server newer than the SDK using an algorithm this SDK version does not know (e.g. a newly introduced algo id >= 3); a corrupted/truncated websocket frame; or test code injecting arbitrary bytes through OnMessageReceived/IsTesting paths.

Common situations: Client SDK package older than a freshly upgraded SpacetimeDB server (version skew); pinned old SDK against maincloud; byte-level test fixtures that forgot the leading algo byte.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16). Data as JSON: /api/errors/df2ec2e262befd07. Report an issue: GitHub.