dotnet/machinelearning · error · InvalidDataException
Malformed varint.
Error message
Malformed varint.
What it means
Thrown at the end of ReadRawVarint32 when ten consecutive bytes all have the continuation bit set, exceeding the maximum width of a protobuf varint. This means the byte stream is not valid protobuf — the SentencePiece reader refuses to continue rather than producing an undefined value.
Source
Thrown at src/Microsoft.ML.Tokenizers/SentencepieceModel.cs:63
return result;
}
}
// Negative int32 values are sign-extended to 10-byte varints; consume remaining bytes.
for (int i = 0; i < 5; i++)
{
if (pos >= end)
{
throw new InvalidDataException("Unexpected end of data while reading varint.");
}
if ((data[pos++] & 0x80) == 0)
{
return result;
}
}
throw new InvalidDataException("Malformed varint.");
}
internal static int ReadLengthPrefix(byte[] data, int end, ref int pos)
{
int length = ReadRawVarint32(data, end, ref pos);
if ((uint)length > (uint)(end - pos))
{
throw new InvalidDataException("Invalid length-delimited field size.");
}
return length;
}
internal static string ReadString(byte[] data, int end, ref int pos)
{
int length = ReadLengthPrefix(data, end, ref pos);
string result = Encoding.UTF8.GetString(data, pos, length);
pos += length;View on GitHub (pinned to 7b76e69cf9)
Solutions
- Confirm the file really is a serialized SentencePiece ModelProto — open the first bytes and check for plausible protobuf framing, not text/HTML.
- Re-export the model from the original source with SentencePiece/protobuf tooling instead of hand-editing or re-encoding it.
- Verify the file was not transferred in text mode (FTP ASCII transfer or charset conversion corrupts binaries).
- If desynchronization is suspected after an earlier error, restart parsing from offset 0 of a validated buffer rather than continuing.
Example fix
// before
// vocab.json mistakenly passed to the SentencePiece tokenizer
var tokenizer = SentencePieceTokenizer.Create(File.ReadAllBytes("vocab.json"));
// after
if (!IsSentencePieceModel(modelPath)) // check magic/framing or correct file
throw new InvalidOperationException($"'{modelPath}' is not a SentencePiece .model protobuf file.");
var tokenizer = SentencePieceTokenizer.Create(File.ReadAllBytes("sentencepiece.bpe.model")); Defensive patterns
Strategy: validation
Validate before calling
// Ensure the file is binary protobuf, not text/HTML/JSON:
bool LooksBinary(byte[] d) => d.Length > 0 && (d[0] == 0x0A || char.IsControl((char)d[0]) == false && d[0] < 0x80 && d[0] != (byte)'<');
if (!LooksBinary(modelBytes))
throw new InvalidDataException("Input does not look like a SentencePiece protobuf model."); Try / catch
try { tokenizer = SentencePieceTokenizer.Create(modelBytes); }
catch (InvalidDataException ex)
{ throw new InvalidOperationException("Data is not valid SentencePiece protobuf (malformed varint). Confirm you are loading the serialized .model file, not a text vocab or error page.", ex); } Prevention
- Confirm the model format before loading: .model = protobuf, vocab files are not
- Check for HTML error pages saved as .model when downloads fail behind proxies
- Never transfer binary models in text/ASCII mode (FTP, charset conversion)
- If parse fails mid-stream, restart from offset 0 on a validated buffer
When it happens
Trigger: ReadRawVarint32 (reached via `length`) consumes bytes at shifts 0..28 and then the negative-value loop (5 more bytes, i == 4 without terminator), totalling more than the protobuf-spec max of 10 bytes, all with bit 0x80 set. Happens when the data is not actually protobuf or is desynchronized mid-stream.
Common situations: Passing a non-protobuf file (e.g. a raw text vocab, a BPE JSON file, or an HTML error page saved as .model) to the SentencePiece tokenizer; parsing a stream whose field framing got desynchronized earlier; binary corruption such as wrong encoding conversion (UTF-8 re-encode of a binary file).
Understand the failure class
Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Unexpected end of data while reading varint.
- Invalid length-delimited field size.
- Unexpected end of data while reading float.
- Unexpected end of data while skipping varint.
- Unexpected end of data while skipping fixed64.
AI-assisted analysis of dotnet/machinelearning@7b76e69cf9 (2026-09-11).
Data as JSON: /api/errors/31c0e1e32f03d55c.
Report an issue: GitHub.