Exception.getMessage() is null
JavaExceptionJava Problem Overview
Inside my Java code, it is checking for !null
condition and throwing an Exception
.
For example
try
{
if (stud.getCall() != null)
acc.Call = stud.getCall().toString();
else
throw new Exception("Data is null");
}
catch (Exception e)
{
logger.error("Some Error" + e.getMessage());
throw new Exception("Please check the Manatadatory Field is Missing" + e.getMessage());
}
But in the logs I am getting:
Some Error null
Why is the e.getMessage
null
?
Java Solutions
Solution 1 - Java
You are catching a different exception to the one that your code is explicitly creating and throwing1. The exception that you are catching doesn't have a message.
You need to log the entire exception, not just the exception's message. Among other things, that would tell you what the caught exception's actual class is and where the exception was created/thrown.
Based on the fact that the exception doesn't have a message, I'd guess that it is an NPE caused by stud
or acc
being null, or by stud.getCall()
returning null
... or something like that. A NullPointerException
generated natively (i.e. by the JVM) has a null
message2.
java.lang.Exception
is Bad Practice
Throwing Your problem illustrates why it is generally speaking a bad idea to create/throw Exception
When you throw Exception
it becomes next to impossible to discriminate between it and other (unexpected) exceptions in a catch
clause. And that is what has happened here: you've caught the wrong exception.
You should pick a more specific exception, and if no appropriate one exists, implement one of your own.
1 - You could use e.printStackTrace()
, a logger call, or a debugger to see which exception you have actually caught.
2 - This is not true on Android. There, an NPE has a helpful message that gives contextual information. It is also no longer true in Java 14 and later; see https://openjdk.java.net/projects/jdk/14/ and https://openjdk.java.net/jeps/358</sup>
Solution 2 - Java
The stack trace is getting written to the log while a message gets written to stdout. My assumption is you don't have permission to see whatever stdout gets written to, so now there is nothing to go on. (Even if you do have rights to see it now you have two separate things to piece together.)
Most logging libraries can log the stacktrace. That way you can keep all the useful information together, adding the exception to the log, not just the message, like
logger.error("caught exception while doing whatever", e);
The stack trace has the exception message, plus the line number that points to the place that caused the exception, and shows you every call along the way, so it's really helpful. And now you've found out not all exceptions include a message.
If whatever you are logging to doesn't handle writing the exception stack trace information, there is code to write the stacktrace as a string here.
The way the posted code throws a new exception is very bad, because you are throwing away the original type of the exception, plus the stacktrace of the original exception. How do you expect to figure out what went wrong when you throw away all the helpful information? If you must catch the exception to log it here, then rethrow the same exception that you caught, or pass the original exception to the new exception as the cause (check out the Throwable constructor arguments), at least that way you don't lose the stacktrace.
You would be better off using a centralized exception handler, letting that do the logging, and have unexpected exceptions go uncaught until they get to the handler. Because once something throws an unexpected exception, your application is in a bad state, any subsequent steps that rely on something this part was supposed to do will fail, and you will get a cascade of errors.
Solution 3 - Java
This is how I fixed the same problem, use this to see the exception:
"" + e);
this will help you when the original programmer threw an Exception object without implementing .getMessage();
I blame Google for allowing Exception objects with null getMessage();
when my code was getting a java.lang.NullPointerException
it was subsequently causing my exception logging to fail on e.getMessage();
the null
from .getMessage();
caused me another unhandled exception and crashed the app with force close message.
so it was this:
Log.e("MainLogger.Run.Exception", e.getMessage());
and I changed it to this Corrected version:
Log.e("MainLogger.Run.Exception", "" + e);
now it gives me a nice string returned java.lang.NullPointerException
Solution 4 - Java
Wanted to comment on hamish's "" + e
answer but I don't have enough reputation points...
It's better to just use e.toString()
instead of "" + e
. The result is the same, but internally, the latter may be doing more work with unnecessary concatenation, involving creating a StringBuilder, appending the blank string, appending the result of e.toString() then converting back to a String. See "3. Addition Operator" of https://www.baeldung.com/java-strings-concatenation for details about StringBuilder being used under the covers.
Regarding the original problem, I'd suggest using e.getString() (or even better, do a full stack trace) instead of just e.getMessage(). For some exceptions the message doesn't make sense without knowing the exception type. An example I've encountered is where e.getMessage() returns "-1", but e.toString() returns "ArrayIndexOutOfBoundsException: -1". Which would you prefer to see in your logs? :-)
Solution 5 - Java
This is late to the party but I'd bet stud
is null and the exception you get is NullPointerException
at if (stud.getCall()....
. It's one of the exception that tend not to have message, i.e. null.
Solution 6 - Java
In my case it was returning the wrong Exception with a null message, because I wrapped the result of the method call in an Optional variable:
It was a call to a MongoRepository database operation:
Optional<CustomerDB> result = Optional.of(repository.findByToken(token));
The function "repository.findByToken(token)" was just returning a CustomerDB object.
I changed the code line to:
CustomerDB result = repository.findByToken(token);
And I got the right exception with the message.
Solution 7 - Java
The code seems fine syntax wise and e.getMessage() should not be null, I compiled the same code and printed the output on console, it printed as "Some ErrorData is null"
which is fine. Now either there is issue with your logger or you might be looking at the wrong line in logger file.
>what can be the issue with logger
It completely depends upon which logger are you using ? Have you overridden the methods of looger.error() ? However it is for sure that e.getMessage() is not null in the catch block. You can also try that by printing e.geMessage() on console in the catch block.
Solution 8 - Java
Before call getMessage() call printStackTrace(). this method
> writes a printable representation of this Throwable's stack trace to > the System.err stream.
try
{
if (stud.getCall() != null)
acc.Call = stud.getCall().toString();
else
throw new Exception("Data is null");
}
catch (Exception e)
{
e.printStackTrace();
logger.error("Some Error" + e.getMessage());
throw new Exception("Please check the Manatadatory Field is Missing" + e.getMessage());
}
Solution 9 - Java
I hope this might help you....
if you want to print the message "Data is null", then instead of using the Build-in class "Exception", try to use the name of your own class where you have wrote this code. for example: if the class name is "DemoClass" (the class where you wrote this code), then write like this:
try{
if (stud.getCall() != null)
acc.Call = stud.getCall().toString();
else
throw new DemoClass("Data is null");
}
catch (DemoClass e){
logger.error("Some Error" + e.getMessage());}
and if you are re-throwing, then don't forget to mention "throws DemoClass" by the side of your function (where this code is written):
throw new DemoClass("Please check the Mandatory Field is Missing" + e.getMessage());