Skip to content

Grav Twig Debugging — Dump, Debug Bar and Variable Inspection

DodaTech Updated 2026-06-27 8 min read

In this tutorial, you'll learn Grav Twig debugging techniques — using the dump function, enabling the debug bar, inspecting template variables, leveraging the DevTools plugin, and troubleshooting common template errors.

What You'll Learn

  • The {{ dump() }} function for variable inspection
  • Grav's debug bar and what it shows
  • The DevTools plugin for development
  • Enabling Twig errors and error reporting
  • Debugging template inheritance and block resolution
  • Performance debugging: template render times, cache hits

Why It Matters

Every developer writes incorrect template code at some point — a variable that doesn't exist, a filter that's misspelled, a block that isn't being overridden. In WordPress, you might var_dump() in PHP or use Query Monitor. In Grav, Twig debugging tools show you exactly what variables are available, which templates are being used, how long each template takes to render, and what configuration values are active. Without these tools, you're guessing.

Real-World Use

A developer is building a custom Grav theme and a template shows blank content. Using {{ dump(page) }}, they discover that page.collection is empty because the frontmatter collection definition uses @self.children but the page has no children. The dump() output reveals the missing data immediately, turning a 30-minute debugging session into a 30-second fix.

Learning Path

flowchart LR
    A["Twig Inheritance"] --> B["Twig Debugging
← You are here"]:::current B --> C["Custom Twig Extensions"] C --> D["Theme Configuration"] D --> E["Theme Assets"] E --> F["Theme Inheritance"] classDef current fill:#38bdf8,color:#0f172a,stroke-width:2px

Dumping Variables

The {{ dump() }} function outputs a structured view of any variable:

{{ dump(page) }}

This shows all properties of the page object: title, content, header, children, parent, url, collection, taxonomy, and more.

Dump Specific Fields

{{ dump(page.title) }}
{{ dump(page.header) }}
{{ dump(page.children) }}
{{ dump(page.collection) }}
{{ dump(config.site) }}

Dump All Variables

{{ dump(_context) }}

The _context variable is a special Twig variable that contains all variables available in the current template context. This is the most comprehensive dump.

Dump with Labels

{{ dump(page, 'Page Object') }}
{{ dump(page.header.taxonomy, 'Taxonomy Data') }}

Enabling the Debug Bar

Grav has a built-in debug bar powered by PHP Debug Bar. Enable it in user/config/system.yaml:

system:
    debugger:
        enabled: true
        twig: true

What the Debug Bar Shows

After enabling, a debug bar appears at the bottom of every page (admin users only by default):

  1. Request tab: Current route, method, and parameters
  2. Configuration tab: All Grav configuration values
  3. Timeline tab: Event timing and template render times
  4. Twig tab: Template names and render times
  5. Cache tab: Cache hits and misses
  6. Messages tab: Debug messages and notices

Twig Tab Details

The Twig tab shows:

Template                Render Time
--------------------------------------------
partials/base.html.twig    1.2ms
default.html.twig          0.8ms
partials/header.html.twig   0.3ms
partials/footer.html.twig   0.2ms

This reveals which template is the slowest, helping you optimize render performance.

DevTools Plugin

The DevTools plugin provides additional debugging capabilities:

bin/gpm install devtools

DevTools Features

  1. Twig variable inspector: Shows all variables available in the current template context with their types and values
  2. Template suggestions: Shows which templates Grav considered and which one was selected
  3. YAML validator: Validates frontmatter YAML syntax
  4. Performance profiler: Detailed timing of Grav events and plugins

Enable DevTools

# user/config/plugins/devtools.yaml
enabled: true
twig: true
profiler: true

Debugging Template Inheritance

When a template is not being used as expected, enable Twig debugging to see template resolution:

# user/config/system.yaml
twig:
    cache: false
    debug: true

Then add to your page:

{# List all template suggestions for this page #}
{# Available only with DevTools plugin #}
{{ dump(page.template()) }}

Debugging Configuration Values

{# Check if a plugin is enabled #}
{{ dump(config.plugins.email.enabled) }}

{# Check site configuration #}
{{ dump(config.site.title) }}
{{ dump(config.site.author) }}

{# List all plugins #}
{{ dump(grav.config.plugins) }}

Debugging Collections

{# Count collection items #}
Collection has {{ page.collection|length }} items.

{# Dump first item #}
{% if page.collection|length > 0 %}
    {{ dump(page.collection|first) }}
{% endif %}

{# List all item titles #}
{% for item in page.collection %}
    {{ item.title }} ({{ item.url }})
{% endfor %}

Debugging Assets

{# List all registered CSS assets #}
{{ dump(grav.assets.css()) }}

{# List all registered JS assets #}
{{ dump(grav.assets.js()) }}

Error Reporting

Enable detailed error messages in development:

# user/config/system.yaml
twig:
    autoescape: true
    auto_reload: true
    cache: false
    debug: true

system:
    debugger:
        enabled: true
        strict: true

With strict: true, Grav shows Twig errors with full backtraces instead of blank pages.

Common Twig Errors

Variable does not exist:

Twig_Error_Runtime: Variable "nonexistent" does not exist.

Fix: Check the variable name or use default('fallback').

Template not found:

Twig_Error_Loader: Unable to find template "partials/missing.html.twig".

Fix: Verify the file path relative to the templates/ directory.

Filter does not exist:

Twig_Error_Syntax: The filter "nonexistent" does not exist.

Fix: Check the filter spelling or install the plugin that provides it.

Performance Debugging

Template Render Times

Add timing markers to identify slow templates:

{% set start = time() %}

{# Your template content here #}

<!-- Template rendered in {{ (time() - start) * 1000 }}ms -->

Cache Debugging

Check if a page is served from cache:

{# Add to base template #}
<!-- Cache key: {{ grav.cache.getKey() }} -->
<!-- Cached: {{ grav.cache.getCacheStatus() ? 'yes' : 'no' }} -->

Logging Debug Messages

{# Log a message (available with Debugger plugin) #}
{% do grav.debugger.addMessage('Custom debug message') %}

Learning Path

flowchart LR
    A["Twig Inheritance"] --> B["Twig Debugging
← You are here"]:::current B --> C["Custom Twig Extensions"] C --> D["Theme Configuration"] D --> E["Theme Assets"] classDef current fill:#38bdf8,color:#0f172a,stroke-width:2px

Common Mistakes

  1. Leaving debug tools enabled in production: The debug bar and Twig debug mode expose sensitive information. Always disable them in production by setting debugger.enabled: false and twig.debug: false.

  2. Dumping without checking if the variable exists: {{ dump(page.collection) }} shows an error if page.collection does not exist. Use a conditional or |default(null) before dumping.

  3. Confusing dump() with print() in Twig: dump() outputs structured debug data with types. {{ page.title }} renders the value. They serve different purposes.

  4. Not clearing cache after enabling debug: Twig debug settings require cache clearing to take effect. Run bin/grav cache --clear after changing debug configuration.

  5. Using var_dump() in PHP instead of Twig dump(): If you are debugging Twig templates, use {{ dump() }} in the template. var_dump() in PHP files prints before the HTML response and breaks the layout.

Practice Questions

  1. How do you view all available variables in a Twig template? Answer: Use {{ dump(_context) }}. The _context variable contains every variable accessible in the current template scope.

  2. What configuration enables Grav's debug bar? Answer: Set system.debugger.enabled: true in user/config/system.yaml. For Twig-specific debugging, also set twig.debug: true.

  3. How do you check if a collection returns any items? Answer: Use {{ page.collection|length }} to count items, or {% if page.collection|length > 0 %} to conditionally check.

  4. What is the difference between twig.cache: false and system.cache.enabled: false? Answer: twig.cache: false disables Twig template Caching only (templates recompile on every request). system.cache.enabled: false disables all Grav caching.

  5. Challenge: Debug a complex template that renders a blog listing page. The blog page shows no content. Use dump() to inspect the page object, the collection, the frontmatter configuration, and the available template variables. Identify which variable is empty and trace the root cause through the template inheritance chain. Document each debugging step and the fix applied.

FAQ

Why is my template showing blank content?

Check if the page has published: true, if the content exists in the Markdown file, if the template is correctly named, and if variables like page.content have values. Use {{ dump(page) }} to inspect the page object.

How do I see which template file is being used?

Enable twig.debug: true and look at the HTML source comments. Grav outputs comments showing which templates were used: <!-- BEGIN OUTPUT from 'templates/default.html.twig' -->.

What does 'Variable does not exist' mean in Twig?

It means you are referencing a Twig variable that has not been set or passed to the template. Check the spelling or use the |default() filter to provide a fallback value.

Can I use xdebug with Twig templates?

Yes, but it is not the most efficient approach. Use Twig's own debugging tools first. If you need to debug PHP code in plugins or theme files, xdebug works normally.

How do I disable the debug bar for non-admin users?

By default, the debug bar only shows for users with admin privileges. You can also set debugger.enabled: true with debugger.mode: 'cli' to limit it to CLI output.

Mini Project

Goal: Debug and optimize a Grav template with performance issues.

  1. Enable the debug bar and Twig debug mode
  2. Create a template that intentionally has errors: missing variable, wrong filter name, incorrect block name
  3. Use {{ dump() }} to identify each error and fix it
  4. Use the debug bar's Timeline tab to identify the slowest template
  5. Use {{ dump(_context) }} to list all available variables
  6. Profile the page before and after enabling Twig cache
  7. Log custom debug messages using grav.debugger.addMessage()
  8. Disable all debug tools and verify the page renders cleanly
  9. Create a development-only configuration that enables debug tools
  10. Document the debugging workflow for future reference

What's Next

Now you can debug any template issue. Next, learn to extend Twig with custom filters and functions:

Continue to Lesson 19: Custom Twig Extensions — Register custom filters, functions, and tests in Grav plugins.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro