HubL lint rules

codefmt's HubL linter runs 28 rules on a single template, across six categories. Each is listed below with its rule id and severity; about ten ship one-click safe fixes via the Fix and Fix (unsafe) buttons. Two further rules (tagged needs project context) only fire when codefmt has your whole theme, so they aren't part of the single-template count.

correctness

Structural errors that stop a template from parsing or rendering.

  • unclosed blockhubl/unclosed-blockerror

    A {% for %}, {% if %}, {% block %}, or other opening tag has no matching {% end... %}.

  • mismatched blockhubl/mismatched-blockerror

    An opening and closing tag don't match, e.g. a {% for %} closed by {% endif %}.

  • unclosed delimiterhubl/unclosed-delimitererror

    A {% %}, {{ }}, or {# #} is opened but never closed.

  • unexpected closerhubl/unexpected-closererror

    A closing tag like {% endif %} appears with no matching opener.

  • elif after elsehubl/elif-after-elseerror

    An {% elif %} appears after {% else %}, where it can never run.

  • unexpected mid-block taghubl/unexpected-miderror

    A mid-block tag like {% else %} or {% elif %} appears outside the block it belongs to.

  • unclosed raw blockhubl/raw-not-closederror

    A {% raw %} block is missing its {% endraw %}.

semantic

Code that parses but means the wrong thing in HubL, including js-mindset traps carried over from JavaScript.

  • unknown filterhubl/unknown-filterinfo

    A filter name isn't a known HubL filter; codefmt suggests the closest match.

  • wrong filter arityhubl/filter-aritywarning

    A filter is called with the wrong number of arguments.

  • unknown globalhubl/unknown-globalinfo

    An identifier isn't a known HubL global or local variable; codefmt suggests the closest match.

  • unknown functionhubl/unknown-functioninfo

    A function call whose name isn't a known HubL function, a locally-defined macro, or an imported name. Method calls and filter calls are excluded.

  • || instead of orhubl/js-trap-orerror

    JavaScript's || used where HubL expects the keyword or.

  • && instead of andhubl/js-trap-anderror

    JavaScript's && used where HubL expects the keyword and.

  • === instead of ==hubl/js-trap-strict-eqerror

    JavaScript's === / !== used where HubL expects == / !=.

  • null instead of nonehubl/js-trap-nullerror

    The literal null used in a test where HubL expects none.

  • backtick template literalhubl/js-trap-template-literalerror

    A JavaScript backtick template literal, which HubL does not support.

  • .forEach instead of a for taghubl/js-trap-foreachinfo

    A JavaScript .forEach() used where HubL expects a {% for %} tag.

inheritance

Mistakes in template inheritance: blocks, extends, and super().

  • duplicate block namehubl/duplicate-block-nameerror

    Two {% block %}s share the same name in one template.

  • missing endblockhubl/missing-endblockerror

    A {% block %} has no matching {% endblock %}.

  • super() outside a blockhubl/super-outside-blockerror

    {{ super() }} is called outside any {% block %}.

  • extends path not foundhubl/extends-path-not-founderrorneeds project context

    {% extends %} points to a template path that doesn't exist in the project. Requires project context.

deprecation

Tags HubSpot has renamed; codefmt flags the old name and offers a safe one-click fix.

  • deprecated taghubl/deprecated-tagwarning

    A deprecated tag such as widget or widget_block that should be renamed to module or module_block. Ships a safe one-click fix.

module shape

Malformed module / dnd_module declarations and field definitions.

  • module missing pathhubl/module-missing-patherror

    A {% module %} or {% dnd_module %} is missing its required path parameter.

  • unknown field typehubl/module-unknown-field-typewarning

    A module field declares a type HubL doesn't recognize.

  • malformed module paramshubl/module-malformed-paramserror

    A module parameter is malformed, e.g. form_id 7a3 where the = was forgotten.

  • unknown module namehubl/module-unknown-namewarningneeds project context

    A {% module %} references a module name not found in the project. Requires project context.

hints

Lower-severity smells: things that work but are worth a second look.

  • nested raw blockhubl/nested-rawwarning

    A {% raw %} block nested inside another {% raw %}, which does not behave as it looks.

  • empty blockhubl/empty-blockwarning

    A block tag with no body content.

  • |safe without |escapehubl/unsafe-without-escapeinfo

    |safe applied without a preceding |escape, a potential XSS footgun.

  • large range loophubl/large-rangeinfo

    range() iterating a very large number of times (over 1000), which can slow template rendering.

run these checks in the HubL formatter and linter

related: why standard linters can't read HubL, codefmt vs. HubSpot's VS Code extension