68

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?

Kevin
  • 702
  • 7
  • 22
Revathi
  • 1,193
  • 9
  • 19
  • 24
  • 1
    Because there is no message set. I would say, you should write your own exception class and set the message – hop Apr 24 '13 at 16:15

10 Answers10

60

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.


Throwing java.lang.Exception is Bad Practice

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

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Indeed a null error message in a NullPointerException is beyond my understanding: I mean it is trying to help a programmer to correct a mistake by creating a second mistake of the same type? – user1708042 Dec 01 '21 at 20:53
  • It is very, very old behavior. Fixing it has the risk of breaking old applications. – Stephen C Dec 01 '21 at 22:35
  • However ... from Java 14 onwards, OpenJDK based JVMs have a command line option to tell them to generate an informative message for NPEs thrown by the JVM itself. See https://openjdk.org/jeps/358. The option is disabled by default, so as not to break applications that depend on the old NPE behavior. – Stephen C Dec 15 '22 at 15:37
21

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.

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
14

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

Igoranze
  • 1,506
  • 13
  • 35
hamish
  • 1,141
  • 1
  • 12
  • 21
  • 5
    Why is it Google's fault? The API design for `Exception` was done by Sun Microsystems in the 1990's! And so was the decision to throw NPE's from the JVM with `null` messages. (Google are the good guys in this because Android platforms throw NPEs with an informative message.) – Stephen C Apr 15 '20 at 00:40
2

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? :-)

Mr Weasel
  • 82
  • 5
1

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.

bestsss
  • 11,796
  • 3
  • 53
  • 63
1

I think this is better

throw new Exception("" + e.getMessage() + " - " + e.getCause());

Because here you get the message and the cause. NOTE: the "" at beginning it's necessary. Or use

throw new Exception(e.getMessage().toString() + " - " + e.getCause().toString());
ToniG
  • 111
  • 1
  • 5
0

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.

Laura Liparulo
  • 2,849
  • 26
  • 27
-1

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());
}
Mehdi
  • 520
  • 1
  • 5
  • 9
-1

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());
-1

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.

Zohaib
  • 7,026
  • 3
  • 26
  • 35