First of all, I would disagree with this statement:
Favour exceptions over error codes
This is not always the case: for example, take a look at Objective-C (with the Foundation framework). There the NSError is the preferred way to handle errors, despite the existence of what a Java developer would call true exceptions: @try, @catch, @throw, NSException class, etc.
However it is true that many interfaces leak their abstractions with the exceptions thrown. It is my belief that this is not the fault of the "exception"-style of error propagating/handling. In general I believe the best advice about error handling is this:
Deal with the error/exception at the lowest possible level, period
I think if one sticks to that rule of thumb, the amount of "leakage" from abstractions can be very limited and contained.
On whether exceptions thrown by a method should be part of its declaration, I believe they should: they are part of the contract defined by this interface: This method does A, or fails with B or C.
For example, if a class is an XML Parser, a part of its design should be to indicate that the XML file provided is just plain wrong. In Java, you normally do so by declaring the exceptions you expect to encounter and adding them to the throws
part of the declaration of the method. On the other hand, if one of the parsing algorithms failed, there's no reason to pass that exception above unhandled.
It all boils down to one thing:
Good interface design.
If you design your interface well enough, no amount of exceptions should haunt you.
Otherwise, it's not just exceptions that would bother you.
Also, I think the creators of Java had very strong security reasons to include exceptions to a method declaration/definition.
One last thing: Some languages, Eiffel for example, have other mechanisms for error handling and simply do not include throwing capabilities. There, an 'exception' of sort is automatically raised when a postcondition for a routine is not satisfied.
I tend to build an application log, either in DB or in file, and log all such information to that. You can then give the user an error number, which identifies which log item the error is related to, so you can get it back. This pattern is also useful as you can follow errors even if the users don't bother raising them with you, so you can get a better idea of where the problems are.
If your site is installed in a client's environment and you can't reach it, you can get the on-site IT dept to send you some extract based on the error no.
The other thing you could consider is having the system email details of errors to a mailbox that you have sight of, so you know when things are going wrong.
Fundamentally having a system that spills its guts when something isn't right doesn't inspire confidence in non-technical users - it tends to scare them into thinking something is very wrong (eg how much of a BSOD do you understand, and how do you feel when one comes up)?
On stacktrace:
In .Net the stack trace will show the full trace right into the core MS sourced assemblies, and will reveal details about what technologies you're using, and possible versions as well. This gives intruders valuable info on possible weaknesses that could be exploited.
Best Answer
You show the user what is actionable for them.
For example, if you have an error which is caused because of some null pointer exception and more of a bug than user error you don't want full explanation because they can't do anything different.
Showing the exception as the primary error message content is pointless for most users. Perhaps if your target user base is developers you could show the information as the full error all the time (maybe you have an internal application for automated testing). But generally users cannot do anything different even with that knowledge.
The best strategy is to do the following:
Example
Note that in some cases you may wish to make the error report be manual vs automatic.