Base64 guide
Fix Rust base64 Invalid symbol 10 offset errors
In Rust base64 decoding, symbol 10 usually means a line feed newline was copied into the encoded value.
What symbol 10 means
The Rust base64 crate decodes encoded text as a strict sequence of Base64 characters. Decimal byte 10 is a line feed. When the error mentions symbol 10, invalid byte 10, or an offset near the end of the string, the decoder often reached a newline that was copied from a PEM block, terminal output, environment variable, log line, or wrapped file. The encoded bytes may be fine, but the surrounding transport added whitespace that the strict decoder does not accept in that mode.
Example
use base64::{engine::general_purpose, Engine as _};
let value = "SGVsbG8gMTAyNGJhc2U=\n";
let decoded = general_purpose::STANDARD.decode(value)?;
use base64::{engine::general_purpose, Engine as _};
let value = "SGVsbG8gMTAyNGJhc2U=\n";
let cleaned = value.trim();
let decoded = general_purpose::STANDARD.decode(cleaned)?;
How to decode it cleanly
- Print or inspect the exact string before decoding. A final newline is easy to miss in logs because it displays as a line break rather than a visible character.
- Use trim() only when the Base64 value is expected to be a single token. It removes leading and trailing whitespace without changing characters inside the encoded data.
- If the value may be wrapped across multiple lines, remove ASCII whitespace intentionally before decoding. Do not blindly remove every character that is not Base64 until you understand the source.
- Pick the matching engine. Use STANDARD for plus and slash values, and URL_SAFE or URL_SAFE_NO_PAD for values that use dash and underscore.
- Check padding after cleanup. A missing equals sign can be separate from the newline error, especially when the input came from a URL-safe token.
When trim is enough
A final line feed is common when a Base64 value is stored in a text file or copied from command output. In that case, trim() is usually the smallest safe fix because the newline sits outside the token. The decoded bytes stay the same because only transport whitespace is removed.
If the value is inside JSON, a header, or a dotenv file, also check for quotes and labels. The decoder should receive only the encoded value, not Bearer prefixes, commas, field names, or surrounding punctuation.
Wrapped Base64 input
Some tools wrap Base64 at fixed line lengths. A strict decoder may reject those embedded line breaks. If the source is a wrapped block and the line breaks are not meaningful, join the lines before decoding.
For security-sensitive values, keep the cleanup rule narrow. Removing every non-Base64 character can hide a corrupted copy. Prefer a small cleanup path that matches the source format you receive.
Common mistakes
- Calling decode on a string that still ends with a newline from read_to_string, clipboard data, or terminal output
- Using STANDARD on a URL-safe value that contains dash or underscore characters
- Removing padding from a value that the receiver expects to remain padded
- Trimming signed token segments and then reusing the modified token as if its signature still matched
- Confusing byte offset with character count when the string was logged with extra wrapper text
Related problems
FAQ
Does symbol 10 always mean a newline?
In this context it usually points to byte value 10, which is line feed. The offset tells you where that byte appeared in the input.
Should I remove all whitespace before decoding?
Only when the source format allows wrapped or padded text. For a single copied token, trim leading and trailing whitespace first.
What if the error changes after trimming?
Then you probably fixed the newline and exposed the next issue, such as missing padding or the wrong Base64 alphabet.