Fix the Unexpected Directive Error in a NetSuite Advanced PDF Template

When Preview fails with Unexpected directive "</#if>", the real damage is usually a few lines higher. Restore the missing directive spaces, then resize the logo and narrow its cell so the invoice header lines up.

The quick answer

The line in the error is where FreeMarker gave up, not where the template broke. Unexpected directive "</#if>" means the closing tag has no valid opening <#if>, so look at the directives above it. A code formatter can strip the space after the directive name, turning <#if .locale=="zh_CN"> into <#if.locale=="zh_CN">. Put the space back in every damaged <#if> and <#elseif>, click Preview, and then fix whatever layout problems the error was hiding.

The screenshots show sample data. Person and company names are fictional. Use your own template and values when following the steps.

Before you start

This example repairs the Wholesale Invoice PDF/HTML Template, an invoice template whose source was run through an external code formatter and pasted back. Since then, Preview fails.

You need the Advanced PDF/HTML Templates feature and a role that can customize templates. Every transaction form that has this template as its Print Template prints with whatever you save, so work on a copy or in a sandbox.

Preview uses sample values, not a particular transaction. Once the template works, print a real invoice from a form that uses it, ideally one with a long company name and address.

01. Open the template in Source Code

Go to Customization > Forms > Advanced PDF/HTML Templates and click Edit on the Wholesale Invoice PDF/HTML Template row. The template was last saved from source code, so it opens with the Source Code toggle on and numbered source lines. Keep working in source mode from here; switching back to the visual editor can rewrite markup and FreeMarker it doesn't fully support.

The template opens in Source Code mode.

02. Read the Preview error

Click Preview. NetSuite shows "Please wait while template code is validated." and then an Error popup: Error on line 10, column 5 in template.

Preview stops with an error on line 10.

Click Detail... to see the full parser message: Unexpected directive, "</#if>". Check if you have a valid #if-#elseif-#else structure.

The detail names the closing if tag as the unexpected directive.

Click Cancel and look at the source. Line 10 is the </#if> that closes the font block. It's a valid closing tag; it's only where the parser noticed something was wrong. The problem is the two directives it's supposed to close. Line 6 reads <#if.locale=="zh_CN"> and line 8 reads <#elseif.locale=="ja_JP">. Both lost the space after the directive name, so FreeMarker doesn't read them as a valid #if and #elseif, and the </#if> on line 10 has nothing to close.

Lines 6 and 8 are missing the space after if and elseif.

The line and column in the error follow the editor's numbering, so they shift if the source gets reformatted or pasted again.

03. Restore the directive spaces

On line 6, click between <#if and .locale and type a space, so it reads <#if .locale=="zh_CN">. On line 8, click between <#elseif and .locale and type a space, so it reads <#elseif .locale=="ja_JP">.

Both directives have their space back.

Click Preview. The template validates and the invoice renders, which shows the layout problems the error was hiding. The logo prints at its full size and runs straight into the Example Supply Co. address. Preview's sample values won't take the zh_CN or ja_JP branches, so if you print in those languages, check one of those invoices too. Click Close preview.

The template renders now, but the logo is huge and overlaps the address.

On line 17, the logo's <img> style is only float: left; margin: 7px;. With no size, it generally prints at the image file's own size, limited only by its cell and the page. Put the cursor after margin: 7px; and type:

width: 150px; height: 60px;

Use values in your logo's own proportions so it isn't stretched. 150 by 60 matches this one.

Line 17 now gives the logo a width and height.

Click Preview. The logo is small now, but the header still doesn't line up. The company name and address start well to the right of the Ship To column, and the invoice number wraps onto two lines as #INV-2026- and 004187. Click Close preview.

The logo fits, but the address sits too far right and the invoice number wraps.

05. Narrow the logo cell

The header is a table, and the logo cell's width pushes the other two columns to the right. On line 15, the cell reads <td rowspan="3" style="width: 330px;">. Change 330px to 170px.

The logo cell drops from 330px to 170px.

Click Preview. The logo sits above Bill To, the Example Supply Co. address starts at the Ship To column, and the Invoice title, #INV-2026-004187, and the date sit over the total box. The invoice number fits on one line. Click Close preview.

The three header columns now line up with Bill To, Ship To, and the total box.

Check the result

  1. Preview opens without an Error popup.
  2. The logo is small and doesn't overlap the address.
  3. The company address starts at the Ship To column.
  4. #INV-2026-004187 fits on one line above the date.

170px is what worked for this template's tables and page width. Yours may need a different number. Change one width, preview, compare, and repeat.

06. Save the repair

Click the arrow next to Save and choose Save and Edit. The page shows "Template was successfully saved." and the source still has the repaired lines, so you can keep working. Preview never saves anything on its own; it validates and renders what's in the editor, and printing keeps using the last saved version until you save. Finish by printing a real invoice from a form that uses this template.

Save and Edit keeps the repair and leaves the editor open.

Common questions

The error says line 10, but line 10 looks fine. Where's the real problem?

Above it. The line and column are where FreeMarker realized something was wrong, which is often below the actual damage. Here line 10 is a valid </#if>; the broken lines are 6 and 8, where <#if and <#elseif lost the space before .locale.

Why did running the source through a code formatter break the template?

Most formatters don't know FreeMarker, so they treat <#if ...> like any other tag and tidy whitespace they think is optional. FreeMarker needs a space between the directive name and its expression. Keep a copy of the source from before formatting so you can compare the lines that changed.

What does "Check if you have a valid #if-#elseif-#else structure" mean?

Every </#if> needs an opening <#if ...> above it, with any <#elseif ...> or <#else> in between. When an opening directive is malformed, FreeMarker doesn't count it, so the closing tag looks unexpected. Check the opening directives before you touch the closing one.

Does Preview save my changes?

No. Preview validates and renders whatever is in the editor, using sample values, and printing keeps using the last saved version. Save with Save or Save and Edit when you're happy with it.

How do I make the logo smaller in an Advanced PDF template?

Give the logo's <img> a width and height in its style, like width: 150px; height: 60px;. Without a size it tends to print at the image file's own size. Pick numbers in your logo's proportions so it doesn't stretch, then preview.

Why does the invoice number wrap, and how do I line up the address with Ship To?

The header is a table, and a wide logo cell pushes the address and the title column to the right, leaving the invoice number too little room. Narrow the logo cell (here from 330px to 170px) and preview again. The right width depends on your template, so change one number at a time.