Because uint8_t is also (probably) unsigned char, for which special rules exist when you perform formatted extraction from a C++ stream.
Unfortunately this is just an alias, not a distinct type.
Basically it's skipping the "lexically convert to a number" step because it thinks you want to pull out a character. The character 'a'.
I think you'll want to read into an unsigned int then downsize if needed.
If you do downsize to a uint8_t, you're also going then to have to promote it back to a larger int (lol) for much the same reason, to trigger serialisation.
To be honest I'd just avoid the small fixed-width types when dealing with streams (unless you're doing unformatted work with read() and write()). It's too easy to forget about this problem.