I have a VF page which must display markups conditionnaly. So I use an outputText tag with a "render" condition. At first, the render condition tested a variable directly:

<apex:outputText rendered="{!theObject.Surface__c > 0 }">

It appears that for some instance records of theObject, the field Surface__c is not populated, which leads to a message "The value 'null' is not valid for operator '>'".

So I try to test if the field has been extracted by my SOQL query.

My idea is to use a Boolean get;set; value, and use try-catch structure to test the field presence and set the boolean value to test in the VF code:

<apex:outputText rendered="{!isSurfacePopulated}">

I tried different coding and did not succeed to trap the exception. I finally ended up with the following Apex code:

public Boolean isSurfacePopulated { get; set; }
public MyControllerExtension(ApexPages.StandardController stdController) {
    ID objID = stdController.getId();
    MyObject theObject = [SELECT Surface__c FROM MyObject WHERE ID = :objID];
    try {
        isSurfacePopulated = theObject.Surface__c > 0;
        system.debug('No Exception triggered');
    catch( Exception e ) {
        system.debug('Exception trapped');
        isSurfacePopulated = false;

Not only I don't trap the exception, but the code doesn't even seem to execute the try block (the debug log doesn't show any of the system.debug() text I specified).

I don't undertstand how that is possible. Do I miss something ?


1 Answer 1


The merge expression engine that Salesforce uses for Visualforce pages operates on slightly different rules than Apex does.

I believe that the way operators work in Apex was changed sometime in the past 2 years or so (around the time the Safe Navigation Operator, ?., was introduced?) to make the comparison operators return false if one argument is null and the other argument is an "Integer, Double, Date, or Datetime". This is part of the scenario that you're experiencing.

So given that, the try/catch isn't necessary in your controller extension.

As for why you're not hitting either debug, the only explanation I can think of is that stdController.getId() is returning null or an Id for a different SObject type. That'd cause your extension's query to return no rows (and run into a No rows for assignment to SObject exception, which is outside of your try/catch).

Double check your logs to see the precise error that you're getting (if any), and double check to see what Id you're sending/receiving (you need to be including id=<record Id here> in the query string for getId() to be able to pick it up).

  • Thank you Derek.
    – fredbe
    Commented Aug 8, 2022 at 17:25
  • Thank you Derek. Let me tell you what I did next. I first rseolved by setting a value in the field Surface__c in every record. Then I could notice that the texte "No exception triggered" appeared in the Debug Log. Then I selected a record and removed value in its Surface__c field : I still can see the "No exception triggered" in the Debug Log, but no error is shown in the VF Page. This behavior still remains a mistery. Besides of that, the Safe Navigation operator works perfectly well.
    – fredbe
    Commented Aug 8, 2022 at 17:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .