In general it improves interoperability between non-human systems.
Say that you have a database. When you ask it for a specific piece of data, and it can't find it, it shows 'data not found'.
Then I build a program that reads information from that database; I program it so that if it receives the text 'data not found' it knows to handle the error somehow.
Ten days later, the guy who programs the database decides that 'oops! we couldn't find the element :(' is a more friendly message to the user. Now my program will stop working until I switch it to the correct error text.
With an error code those kind of things don't happen. If you need extra legibility you can totally send both a code and a message, but the code is expected to remain unchanged and I can trust that it will stay the same in the future.
Grouping behaviours is another use. For example, if I have a system that sends you information and you have sent me wrong input, there's a dozen ways you could have done that (maybe you didn't send me enough data, or you sent it in chinese characters I don't recognise, or I just got gibberish I can't even start to understand). All of those cases might require different messages to the final user, but internally for me they're the same thing ('invalid data') and the things I'll have to do will be the same, so propagating a code serves me well.
There's also the issue of internationalization. If 200 android users across the world are having problems with their phones, and they all get an error 3242, they'll be able to find proper help. If one is showing "the application couldn't start due to memory issues", the other "la aplicacion no pudo iniciarse por problemas con la memoria" and yet another shows "لا يمكن بدء التطبيق بشكل صحيح" we're gonna have trouble identifying all those things as the same problem.
Say that you have a database. When you ask it for a specific piece of data, and it can't find it, it shows 'data not found'.
Then I build a program that reads information from that database; I program it so that if it receives the text 'data not found' it knows to handle the error somehow.
Ten days later, the guy who programs the database decides that 'oops! we couldn't find the element :(' is a more friendly message to the user. Now my program will stop working until I switch it to the correct error text.
With an error code those kind of things don't happen. If you need extra legibility you can totally send both a code and a message, but the code is expected to remain unchanged and I can trust that it will stay the same in the future.
Grouping behaviours is another use. For example, if I have a system that sends you information and you have sent me wrong input, there's a dozen ways you could have done that (maybe you didn't send me enough data, or you sent it in chinese characters I don't recognise, or I just got gibberish I can't even start to understand). All of those cases might require different messages to the final user, but internally for me they're the same thing ('invalid data') and the things I'll have to do will be the same, so propagating a code serves me well.
There's also the issue of internationalization. If 200 android users across the world are having problems with their phones, and they all get an error 3242, they'll be able to find proper help. If one is showing "the application couldn't start due to memory issues", the other "la aplicacion no pudo iniciarse por problemas con la memoria" and yet another shows "لا يمكن بدء التطبيق بشكل صحيح" we're gonna have trouble identifying all those things as the same problem.