IsNull
Tests a value for a genuine null. Runtime-proven on a live Marketing Cloud Engagement CloudPage — where it returned False for every input a page variable can hold, including the unset variable the official example says returns true.
Syntax
IsNull(value) → boolean
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
value |
string | number | boolean | date | Yes | Value to test — typically a data extension field value retrieved with Lookup |
Example
The intended use is a data extension field that may carry no value at all:
%%[
VAR @nickname
SET @nickname = Lookup("Preferences", "Nickname", "SubscriberKey", _subscriberkey)
]%%
%%=IIf(IsNull(@nickname), "no nickname on file", @nickname)=%%
Reaching for it anywhere else silently takes the false branch. On a CloudPage this renders present even though nothing was ever assigned:
%%[ VAR @maybe ]%%
%%=IIf(IsNull(@maybe), "missing", "present")=%%
Use Empty for that check — for the same variable it renders True.
Return value
boolean — False when the value is not null.
Only the False literal was observed. Every one of the sixteen inputs probed rendered it, and the true token was never produced — so no set of return literals is claimed here, even though the sibling Empty proved the engine renders True readily for a boolean-returning Utility function.
Behaviour
Nothing a page variable can hold is null. An undeclared variable, a variable declared but never assigned, the empty string, three spaces, 0, "0", "false", an ordinary string and a date value each returned False.
Missing context is not null either. An attribute that does not exist, a query-string parameter that was not supplied, _subscriberkey, firstname, _messagecontext and jobid on an anonymous page request all returned False — as did an unset variable routed through v() and through Concat(), in case the accessor rather than the value decided the answer.
A non-string argument is accepted. IsNull(0) and IsNull(Now()) both rendered at HTTP 200 rather than aborting.
The community guide’s framing matches what was observed: the function answers a question about data extension field values, and reports false everywhere else.
The unset variable the official example promises
The official reference’s own usage example declares a variable with VAR, never assigns it, and states the result is true. That exact shape returned False. The gate printed its own start and done markers at HTTP 200 alongside a known-good control block, so the page ran to completion — this is a result, not a swallowed abort. See the differs-from-docs card.
How the four Utility tests compare
The same inputs put through all four functions, on one page, in one run:
| Input | Empty |
IsNull |
IsNullDefault(x, "DEF") |
IIf(x, "T", "F") |
|---|---|---|---|---|
| undeclared variable | True | False | (empty) | F |
| declared, never set | True | False | (empty) | F |
"" |
True | False | (empty) | F |
" " |
False | False | ` ` | F |
0 |
False | False | 0 |
F |
"0" |
False | False | 0 |
F |
"false" |
False | False | false |
F |
"hello" |
False | False | hello |
F |
The IsNull column is constant. That is the practical summary: for a missing-value test on a page, this is the wrong function.
Show test script
%%[
VAR @b, @unset, @es, @sp, @z, @z0, @sf, @val
SET @b = RequestParameter("b")
SET @es = ""
SET @sp = " "
SET @z = 0
SET @z0 = "0"
SET @sf = "false"
SET @val = "hello"
/* known-good control: renders on every request, so a run of HTTP 422s
can be told apart from a broken deploy */
OutputLine(Concat("CTRL=[", Uppercase("ok"), "]"))
/* a name that was never declared */
IF @b == "n_und" THEN
OutputLine(Concat("--- n_und start ---"))
OutputLine(Concat("N_UND=[", IsNull(@zzz_never_declared), "]"))
OutputLine(Concat("--- n_und done ---"))
ENDIF
/* declared with VAR, never assigned - the shape the official example uses */
IF @b == "n_unset" THEN
OutputLine(Concat("--- n_unset start ---"))
OutputLine(Concat("N_UNSET=[", IsNull(@unset), "]"))
OutputLine(Concat("--- n_unset done ---"))
ENDIF
/* the explicitly empty string - the documented difference from Empty */
IF @b == "n_es" THEN
OutputLine(Concat("--- n_es start ---"))
OutputLine(Concat("N_ES=[", IsNull(@es), "]"))
OutputLine(Concat("E_ES=[", Empty(@es), "]"))
OutputLine(Concat("--- n_es done ---"))
ENDIF
/* three spaces */
IF @b == "n_sp" THEN
OutputLine(Concat("--- n_sp start ---"))
OutputLine(Concat("N_SP=[", IsNull(@sp), "]"))
OutputLine(Concat("--- n_sp done ---"))
ENDIF
/* the number zero, as a variable and inline */
IF @b == "n_z" THEN
OutputLine(Concat("--- n_z start ---"))
OutputLine(Concat("N_Z=[", IsNull(@z), "]"))
OutputLine(Concat("N_ZLIT=[", IsNull(0), "]"))
OutputLine(Concat("--- n_z done ---"))
ENDIF
/* the string "0" */
IF @b == "n_z0" THEN
OutputLine(Concat("--- n_z0 start ---"))
OutputLine(Concat("N_Z0=[", IsNull(@z0), "]"))
OutputLine(Concat("--- n_z0 done ---"))
ENDIF
/* the string "false" */
IF @b == "n_sf" THEN
OutputLine(Concat("--- n_sf start ---"))
OutputLine(Concat("N_SF=[", IsNull(@sf), "]"))
OutputLine(Concat("--- n_sf done ---"))
ENDIF
/* a genuine value, as a variable and inline */
IF @b == "n_val" THEN
OutputLine(Concat("--- n_val start ---"))
OutputLine(Concat("N_VAL=[", IsNull(@val), "]"))
OutputLine(Concat("N_VLIT=[", IsNull("hello"), "]"))
OutputLine(Concat("--- n_val done ---"))
ENDIF
/* a date value, to show a non-string argument is accepted */
IF @b == "n_date" THEN
OutputLine(Concat("--- n_date start ---"))
OutputLine(Concat("N_DATE=[", IsNull(Now()), "]"))
OutputLine(Concat("--- n_date done ---"))
ENDIF
/* an attribute that does not exist */
IF @b == "a_attr" THEN
OutputLine(Concat("--- a_attr start ---"))
OutputLine(Concat("N_ATTR=[", IsNull(AttributeValue("zzNoSuchAttribute")), "]"))
OutputLine(Concat("E_ATTR=[", Empty(AttributeValue("zzNoSuchAttribute")), "]"))
OutputLine(Concat("--- a_attr done ---"))
ENDIF
/* a query-string parameter that was not supplied */
IF @b == "a_rp" THEN
OutputLine(Concat("--- a_rp start ---"))
OutputLine(Concat("N_RP=[", IsNull(RequestParameter("zzNoSuchParam")), "]"))
OutputLine(Concat("E_RP=[", Empty(RequestParameter("zzNoSuchParam")), "]"))
OutputLine(Concat("--- a_rp done ---"))
ENDIF
/* the subscriber key on an anonymous page request */
IF @b == "s_sub" THEN
OutputLine(Concat("--- s_sub start ---"))
OutputLine(Concat("N_SUB=[", IsNull(_subscriberkey), "]"))
OutputLine(Concat("E_SUB=[", Empty(_subscriberkey), "]"))
OutputLine(Concat("--- s_sub done ---"))
ENDIF
/* a profile attribute outside a send */
IF @b == "s_prof" THEN
OutputLine(Concat("--- s_prof start ---"))
OutputLine(Concat("N_PROF=[", IsNull(firstname), "]"))
OutputLine(Concat("E_PROF=[", Empty(firstname), "]"))
OutputLine(Concat("--- s_prof done ---"))
ENDIF
/* send-context tokens that only exist inside a job */
IF @b == "s_msgctx" THEN
OutputLine(Concat("--- s_msgctx start ---"))
OutputLine(Concat("N_MSG=[", IsNull(_messagecontext), "]"))
OutputLine(Concat("N_JOB=[", IsNull(jobid), "]"))
OutputLine(Concat("--- s_msgctx done ---"))
ENDIF
/* the unset variable routed through two different accessors, in case the
accessor rather than the value decides the answer */
IF @b == "s_var" THEN
OutputLine(Concat("--- s_var start ---"))
OutputLine(Concat("N_V=[", IsNull(v(@unset)), "]"))
OutputLine(Concat("N_CONCAT=[", IsNull(Concat(@unset)), "]"))
OutputLine(Concat("--- s_var done ---"))
ENDIF
]%%
Proving the true literal needs a data extension field holding a genuine database null. Two attempts to build one — inserting a row with unset columns, then a bare lookup against the same data extension — both aborted the page at compile time, including on a plain request with no branch selected. Nothing from those deploys was attributed to the function, and the check remains open rather than guessed at.
Availability
| Platform | Available |
|---|---|
| Marketing Cloud Engagement | Yes |
| Marketing Cloud Next | Yes (since 67) |
See also
- Empty — what to use instead for a missing-value test; it separates the inputs this function cannot
- IsNullDefault — the same null definition with a fallback value bolted on
- IIf — what usually consumes the boolean
- The unset variable is not reported as null
- Official reference · ampscript.guide