Explain the failure at the right level
Distinguish invalid input from an unavailable service and from a request whose outcome is uncertain. The person can correct a missing field, but cannot fix a database connection by retyping the same information.
Use the vocabulary of the task. A reference code can help support investigate, but should not be the whole explanation. Keep implementation details and sensitive diagnostics in protected operational records rather than exposing them in the interface.
Avoid blaming the wrong cause
Do not say “incorrect password” when the authentication service could not be reached. Do not say “saved” merely because a request left the browser. The message should reflect what the application knows about the outcome.
Where an operation may have completed despite a timeout, provide a way to check or safely retry. Design that behavior with the backend; reassuring copy cannot make a duplicate-sensitive action safe on its own.
Preserve the path forward
Keep form input after a recoverable failure and identify the field that needs attention. For a system problem, tell the user whether waiting, retrying, or contacting support is appropriate. Avoid presenting a retry button when repeating the same request cannot help.
Read the message with the surrounding page. Does the button still describe the next action? Can a keyboard user reach the problem? Does a person returning later understand which item failed?
Review error cases as part of normal product design. They are often the moments when people need the clearest explanation, especially when they have already invested time in the task.
A practical example.
Suppose a user tries to upload a file that exceeds the supported size. “Upload failed” leaves them guessing. A useful message identifies the limit, says the file was not saved, and suggests a smaller file or an alternative route if one exists.
A different message is needed when the connection fails after the upload starts and the final result is unknown. Avoid confidently telling the user that nothing happened. Offer a way to check the record or safely retry according to the application’s behavior. Keep operational details, such as a correlation reference, available for support without exposing internals in the main message. Preserve the user’s work wherever recovery allows it.
Put it into practice.
- Explain what happened, what remains saved, and what the user can do next.
- Distinguish a known rejection from an operation whose outcome is uncertain.
- Put support references in secondary detail and keep the main instruction readable.