There is a String object called detailMessage in java.lang.Throwable class, which says the reason of any exception thrown in java code.

This object is initialized through a constructor using super(string message) statement or setter or whatever from subclasses like Exception and again from its subclasses like SQLException.

When SQLException is thrown, error message can be displayed using sqlExceptionObject.getMessage();

The error message in sqlExceptionObject.getMessage() is same as in MySQL tool (Incase of any error in query execution)

So is the error message copied from MySQL? If yes, then from where?

It's probably part of the line protocol that the MySQL driver on your client uses to communicate with the MySQL server. You would not normally need to concern yourself with such things. But if you want to learn more, see MySQL: 8.3. The NDB Communication Protocol