Skip to main content

Tera usage and troubleshooting

Use this guide to build, validate, and troubleshoot Tera templates in Notification Center. The guide covers common issues, error-prevention techniques, and best practices when writing dynamic templates for connectors, presets, and routing rules.

For full syntax, filters, and operators, see the Tera documentation (external link).

1. Handle missing fields to avoid rendering failures​

If a required field is missing from the data, template rendering fails.

To prevent this, always provide a default value or check if the variable is defined before using it.

Use a default value​

{{ featureName | default('Unknown Feature') }}

Check if a variable exists​

{%- if featureName is defined -%}
{{ featureName }} is released!
{%- elif bugDescription is defined -%}
Bug reported: {{ bugDescription }}
{%- else -%}
NA
{%- endif -%}

Undefined variables cause render errors. Always guard or default optional fields.

2. Prevent JSON parsing failures in presets​

Symptom​

  • Template fails to render.
  • JSON parsing errors appear.
  • Happens when inserting unescaped text into JSON fields.

Cause​

If the rendered value contains unescaped quotes, the JSON field becomes invalid.

Solution: sanitize fields with json_encode​

Always encode free-form strings inserted into JSON.

Correct:

{
"description": {{ alertDef.description | json_encode }}
}

Incorrect:

{
"description": "Some description with "Quotes inside" "
}

json_encode escapes internal quotes and ensures valid JSON.

3. Fix is conditions used on missing fields​

Symptom​

Conditions like:

alertDef.entityLabels["key"] is containing("value")

fail with: Test call failed.

Cause​

String tests fail if the field is undefined.

Solution: guard with is defined​

alertDef.entityLabels["key"] is defined
and alertDef.entityLabels["key"] is containing("value")

Regex example:

alertDef.entityLabels["service"] is defined
and alertDef.entityLabels["service"] is matching("checkout")

4. Format dates from timestamps​

Convert timestamps to readable dates using the date filter.

Tera expects timestamps in seconds, so convert milliseconds or other units before formatting. Use epoch_seconds to safely handle raw numeric timestamps:

{{ maintenanceDate | epoch_seconds | date(format="%d/%m/%y - %H:%M:%S") }}

If timezone information is also needed (using %Z or %z), supply a timezone parameter to the date function. In nearly all cases, timestamps are UTC, so specify UTC explicitly:

{{ maintenanceDate | epoch_seconds | date(format="%d/%m/%y - %H:%M:%S %Z", timezone="UTC") }}

Without the timezone parameter, the template will fail to render.

However, if the input value is already a date string (e.g., 2022-02-02, 2022-02-02T12:34:56, 2022-02-02T12:34:56+0100), the timezone parameter is not required: Tera will infer UTC or the correct timezone automatically.

5. Define variables to simplify logic​

Assign variables using set to avoid repetition.

{%- set priority = alert.highestPriority | default(value=alert.priority) -%}
{%- if priority == "P1" -%}
critical
{%- elif priority == "P2" -%}
error
{%- elif priority == "P3" -%}
warning
{%- else -%}
info
{%- endif -%}

Variable scope inside loops​

Use set_global when a value must persist outside a loop.

{% set default_key = "default_key" %}

{% for s in keys %}
{% if s[0] == alertDef.someService %}
{% set_global default_key = "" %}
{% break %}
{% endif %}
{% endfor %}

{{ default_key }}

6. Iterate over key–value pairs​

{% for key, value in _context.entityLabels %}
{{ key }}: {{ value }}{% if not loop.last %}, {% endif %}
{% endfor %}

Use this pattern to print all labels dynamically.

7. Remove extra spaces and newlines​

Tera preserves whitespace. Trim using {%- and -%}.

{%- for item in items -%}
Example
{%- endfor %}

Keeps rendered output compact.

8. Explore available variables​

Print the entire context:

{{ get_context() | json_encode(pretty=true) }}

This reveals objects such as alertDef, alert, case, and _context.

Note

Use schema references for accurate field names:

9. Extract alert log example​

The get_log function extracts alert log examples. Use it only in alert-related templates.

{{ get_log() | json_encode(pretty=true) }}

10. Project JSON object fields​

To extract a subset of JSON object fields, use the pick function. Construct the resulting object by using either include or exclude projection parameters:

{# The resulting object will contain `priority`, `metrics.value` keys #}
{{ get_log() | pick(include = ["priority", "metrics.value"]) | json_encode(pretty = true) }}

{# The resulting object will contain everything except `metrics` key #}
{{ get_log() | pick(exclude = ['metrics']) | json_encode(pretty = true) }}

{# Error. It doesn't support brackets based indexing, use .<index> instead #}
{{ get_log() | pick(include = ['groups[0].value']) | json_encode(pretty = true) }}
{# The resulting object will contain {groups: [null, {value: ...}]} #}
{{ get_log() | pick(include = ['groups.1.value']) | json_encode(pretty = true) }}

Next steps​

See a complete walkthrough of routing alert notifications to Slack in Example: route alerts to Slack.

Last updated on