There's a well established pattern for useful error messages:
1) What went wrong
2) Why (identifying information for the developer to fix, if applicable)
3) What the user can do about it
For example:
"The database connection could not be made. SQL Server error 12345: Out of Cheese. Please contact product support. (OK)"
"Cannot save the document. Disk not found. Insert a disk in Drive A. (Retry)/(Cancel)"
and so on
Also, it's best to log unexpected errors, because the user will never relay the actual error message to you. They'll hit the OK button THEN call you. Having a log file on disk with the error details and stack trace is usually the most helpful thing when diagnosing a bug.