At this time (Spring '15) I don't know of a way to both prevent the DML operation and to display a user-friendly error message. You may want to promote this idea titled, "Process Builder: Error messages" which could give us more options to more gracefully handle errors in the future.
Here's what I've tried:
sObject.addError(String). This has no impact that I can tell with the process. The DML operation completes as if I never called the method.
sObject.field.addError(String). This also has no impact that I can tell with the process. The DML operation again completes as if I never called the method.
throw a custom exception. This simply generates an ugly flow exception that is no different from any other unhandled exception encountered during Apex execution.
- Write an error message back to a field on the record being processed. This causes an ugly flow exception like the one described above. The reason is that you can't write back to the record, since it's read-only by the time it gets to the action.
The next best alternative (I think) would be either to send an email to the user to explain the problem or to post to the record's Chatter feed with an explanation of the problem, mentioning the user. Or you could do both of those and also include an admin on the notification.