Base64 guide
Fix Rust base64 Invalid symbol 10 offset errors
In Rust base64 decoding, symbol 10 is byte 0x0A: a line feed copied into the encoded value.
What symbol 10 means
The Rust base64 crate treats the input as Base64 bytes, not as a loose text block. 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 input contains a newline from a PEM block, terminal output, environment variable, log line, or wrapped file. The encoded value can still be valid after that transport whitespace is removed.
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
- Inspect the exact bytes before decoding. A final newline disappears into the log output unless you print the escaped string or check value.as_bytes().
- Use trim() for a single-token value from a file, clipboard, or command output. It removes whitespace around the token and leaves characters inside the token alone.
- For a wrapped Base64 block, remove only ASCII whitespace before decoding. Keep the cleanup rule tied to the source format.
- Use STANDARD for values containing plus and slash. Use URL_SAFE or URL_SAFE_NO_PAD for values containing dash and underscore.
- After whitespace cleanup, check padding separately. A missing equals sign is a different problem from symbol 10.
When trim is enough
A trailing line feed is common when a Base64 value is stored in a text file or copied from command output. For one copied token, trim() is enough: the newline sits outside the token, so the decoded bytes do not change.
If the value comes from JSON, a header, or a dotenv line, strip the container first. The decoder input must be only the encoded value: no Bearer prefix, comma, field name, quote, or surrounding punctuation.
Wrapped Base64 input
Some encoders wrap Base64 at fixed line lengths. A strict decoder rejects those embedded line feeds. When the source is a wrapped block, join the lines first.
For tokens, headers, and signed values, keep cleanup narrow. Removing every non-Base64 character can hide a bad copy. Remove only whitespace or wrapper text that comes from the source format.
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 Rust error, symbol 10 is byte value 10, line feed. The offset is the byte position in the input.
Do I remove all whitespace before decoding?
For wrapped Base64 blocks, yes. For a copied token, trim leading and trailing whitespace first and leave internal characters intact.
What if the error changes after trimming?
That means the newline was removed and the decoder reached the next issue, such as missing padding or the wrong Base64 alphabet.