Even if you make it hard for a user to make a mistake, expect your program to have to deal with errors. It is possible for a program to handle errors in a way that doesn't leave the user wondering what happened. When code is written, errors of all sorts need to be anticipated and handled, such as lack of memory, lack of disk space, permissions errors, corrupted files, and loss of network connectivity. As Murphy's Law states, if something can go wrong in a given situation, it probably will. Hope for the best but prepare for the worst: without bordering on the completely ridiculous, handle every error that is likely to occur. Doing so greatly improves the perception of your software by the outside world. Crashes are unacceptable in all cases. Period. Error messages, for example, need to describe at the user's level of expertise what happened and suggest what the user can do to remedy the situation. In the worst case, the program needs to provide an easy way for the user to send technical information about the problem back to you via e-mail or some other means. In all cases, the user's data is to be preserved.
One way that you can see how well your program handles errors is to deliberately try to break it in every way possible. Feed the entire text of your Aunt May's quiche recipe into a text box all at once. Try to open files it has no business being given. Take a valid document, back it up, open it in DiskProbe, enter as much junk data into it as you like, and then try to open it. Break your Internet connection while it's in the middle of an update. Try to using filenames with really wonky filenames. Be creative and ridiculous and, most of all, have fun breaking things!