dotnet/machinelearning · error · FormatException
Invalid base64 string '{base64String.Substring(offset, lengt
Error message
Invalid base64 string '{base64String.Substring(offset, length)}' What it means
Helpers.FromBase64String validates the requested substring with Base64.IsValid before decoding, and throws this FormatException when the slice is not valid base64 (bad characters, wrong length/padding, embedded whitespace). The method decodes a portion of a larger string (e.g. a vocab entry), so an offset/length that doesn't align to a complete base64 blob triggers this.
Source
Thrown at src/Microsoft.ML.Tokenizers/Utils/Helpers.netcoreapp.cs:40
{
public static ValueTask<string?> ReadLineAsync(StreamReader reader, CancellationToken cancellationToken) =>
reader.ReadLineAsync(cancellationToken);
public static Task<Stream> GetStreamAsync(HttpClient client, string url, CancellationToken cancellationToken = default) =>
client.GetStreamAsync(url, cancellationToken);
public static Stream GetStream(HttpClient client, string url)
{
HttpResponseMessage response = client.Send(new HttpRequestMessage(HttpMethod.Get, url), HttpCompletionOption.ResponseHeadersRead);
response.EnsureSuccessStatusCode();
return response.Content.ReadAsStream();
}
public static byte[] FromBase64String(string base64String, int offset, int length)
{
if (!Base64.IsValid(base64String.AsSpan(offset, length), out int decodedLength))
{
throw new FormatException($"Invalid base64 string '{base64String.Substring(offset, length)}'");
}
byte[] bytes = new byte[decodedLength];
bool success = Convert.TryFromBase64Chars(base64String.AsSpan(offset, length), bytes, out int bytesWritten);
Debug.Assert(success);
Debug.Assert(bytes.Length == bytesWritten);
return bytes;
}
internal static bool TryParseInt32(string s, int offset, out int result)
=> int.TryParse(s.AsSpan().Slice(offset), NumberStyles.None, CultureInfo.InvariantCulture, out result);
internal static int GetHashCode(ReadOnlySpan<char> span) => string.GetHashCode(span);
internal static unsafe int GetUtf8Bytes(ReadOnlySpan<char> source, Span<byte> destination)
=> Encoding.UTF8.GetBytes(source, destination);
internal static unsafe bool TryGetUtf8Bytes(ReadOnlySpan<char> source, Span<byte> destination, out int bytesWritten)View on GitHub (pinned to 7b76e69cf9)
Solutions
- Fix the offset/length calculation so the slice covers exactly the base64 payload (excluding delimiters/quotes).
- Pre-validate with Base64.IsValid(span) and log/repair the offending entry instead of crashing.
- Check whether the vocab file format matches what the tokenizer version expects; regenerate the vocab.
- Trim stray whitespace/quotes from the slice before decoding.
Example fix
// before: length includes the trailing delimiter int len = lineEnd - start; // includes ',' byte[] b = Helpers.FromBase64String(line, start, len); // after int len = lineEnd - start; if (line[len-1] == ',') len--; byte[] b = Helpers.FromBase64String(line, start, len);
Defensive patterns
Strategy: validation
Validate before calling
if (!Base64.IsValid(textSpan)) throw new FormatException($"Invalid base64 at offset {offset}, length {length}");
byte[] bytes = Helpers.FromBase64String(s, offset, length); Type guard
static bool IsValidBase64Slice(string s, int offset, int length) => offset >= 0 && length >= 0 && offset + length <= s.Length && Base64.IsValid(s.AsSpan(offset, length));
Try / catch
try { bytes = Helpers.FromBase64String(s, offset, length); }
catch (FormatException ex)
{ log.LogError(ex, "Bad base64 token in vocab"); bytes = Array.Empty<byte>(); } Prevention
- Compute slice bounds excluding delimiters/quotes
- Pre-validate with Base64.IsValid before decoding
- Keep vocab file format and parser offsets in sync per library version
When it happens
Trigger: Calling FromBase64String(s, offset, length) with a slice containing non-base64 characters, missing padding, or a length not a multiple of 4 — commonly when the offset/length arithmetic over the containing string is off by a delimiter or quote character.
Common situations: Parsing a byte-level BPE vocab where each token is stored as base64, but the file format changed (extra delimiters, JSON-escaped content) so offsets are computed incorrectly; hand-editing vocab files; mixing vocab formats across library versions.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Invalid format of merge file at line: "{line}"
- Invalid format of merge file at line: "{line}"
- The tokenizer.json normalizer 'precompiled_charsmap' is not
- Empty file
- Failed to decode token ids
AI-assisted analysis of dotnet/machinelearning@7b76e69cf9 (2026-09-11).
Data as JSON: /api/errors/e93c6b2f373829c3.
Report an issue: GitHub.