squidfunk / mkdocs-material

Documentation that simply works
https://squidfunk.github.io/mkdocs-material/
MIT License
20.85k stars 3.53k forks source link

dict object has no element Undefined (Jinja 3.0.1) #3356

Closed kcgthb closed 2 years ago

kcgthb commented 2 years ago

Contribution guidelines

I've found a bug and checked that ...

Description

New page icons in version 8.1.2+insiders.4.5.0 seem to be breaking whole site rendering.

mkdocs serve fails with a backtrace that ends like this:

material/partials/nav-item.html", line 5, in template
    {% if "icon" in meta[nav_item.url] %}
jinja2.exceptions.UndefinedError: dict object has no element Undefined

This is without any page containing the new icon metadata.

Reverting to 8.1.2+insiders.4.5.0 without any other change resolves the problem.

Expected behaviour

Site builds successfully ;)

Actual behaviour

Build breaks:

$ mkdocs build
INFO     -  [macros] - Macros arguments: {'module_name': 'main', 'modules': [], 'include_dir': '', 'include_yaml':
            ['includes/data/software.yml', 'includes/data/facts.yml'], 'j2_block_start_string': '', 'j2_block_end_string': '',
            'j2_variable_start_string': '', 'j2_variable_end_string': '', 'verbose': False}
INFO     -  [macros] - Loading yaml file: /home/kilian/Work/Web/sherlock/main/includes/data/software.yml
INFO     -  [macros] - Loading yaml file: /home/kilian/Work/Web/sherlock/main/includes/data/facts.yml
INFO     -  [macros] - Extra variables (config file): ['analytics', 'consent', 'generator', 'social', 'made_in',
            'support_email', 'purge_days']
INFO     -  [macros] - Extra filters (module): ['pretty']
INFO     -  Cleaning site directory
INFO     -  Building documentation to directory: /home/kilian/Work/Web/sherlock/main/site
INFO     -  The following pages exist in the docs directory, but are not included in the "nav" configuration:
              - index.md
              - docs/tags.md
Traceback (most recent call last):
  File "/home/kilian/.local/bin/mkdocs", line 8, in <module>
    sys.exit(cli())
  File "/usr/lib/python3/dist-packages/click/core.py", line 1126, in __call__
    return self.main(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/click/core.py", line 1051, in main
    rv = self.invoke(ctx)
  File "/usr/lib/python3/dist-packages/click/core.py", line 1657, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/lib/python3/dist-packages/click/core.py", line 1393, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/lib/python3/dist-packages/click/core.py", line 752, in invoke
    return __callback(*args, **kwargs)
  File "/home/kilian/.local/lib/python3.9/site-packages/mkdocs/__main__.py", line 187, in build_command
    build.build(config.load_config(**kwargs), dirty=not clean)
  File "/home/kilian/.local/lib/python3.9/site-packages/mkdocs/commands/build.py", line 306, in build
    _build_theme_template(template, env, files, config, nav)
  File "/home/kilian/.local/lib/python3.9/site-packages/mkdocs/commands/build.py", line 111, in _build_theme_template
    output = _build_template(template_name, template, files, config, nav)
  File "/home/kilian/.local/lib/python3.9/site-packages/mkdocs/commands/build.py", line 90, in _build_template
    output = template.render(context)
  File "/usr/lib/python3/dist-packages/jinja2/environment.py", line 1304, in render
    self.environment.handle_exception()
  File "/usr/lib/python3/dist-packages/jinja2/environment.py", line 925, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "/home/kilian/Work/Web/sherlock/main/overrides/404.html", line 1, in top-level template code
    {% extends "main.html" %}
  File "/home/kilian/Work/Web/sherlock/main/overrides/main.html", line 1, in top-level template code
    {% extends "base.html" %}
  File "/home/kilian/.local/lib/python3.9/site-packages/material/base.html", line 158, in top-level template code
    {% block site_nav %}
  File "/home/kilian/.local/lib/python3.9/site-packages/material/base.html", line 166, in block 'site_nav'
    {% include "partials/nav.html" %}
  File "/home/kilian/.local/lib/python3.9/site-packages/material/partials/nav.html", line 27, in top-level template code
    {% include "partials/nav-item.html" %}
  File "/home/kilian/.local/lib/python3.9/site-packages/material/partials/nav-item.html", line 101, in top-level template code
    {{ render(nav_item, path, level) }}
  File "/usr/lib/python3/dist-packages/jinja2/runtime.py", line 828, in _invoke
    rv = self._func(*arguments)
  File "/home/kilian/.local/lib/python3.9/site-packages/material/partials/nav-item.html", line 40, in template
    {{ render_content(nav_item) }}
  File "/usr/lib/python3/dist-packages/jinja2/runtime.py", line 828, in _invoke
    rv = self._func(*arguments)
  File "/home/kilian/.local/lib/python3.9/site-packages/material/partials/nav-item.html", line 5, in template
    {% if "icon" in meta[nav_item.url] %}
jinja2.exceptions.UndefinedError: dict object has no element Undefined

Steps to reproduce

  1. pip install --user --upgrade git+https://github.com/squidfunk/mkdocs-material-insiders.git@8.1.2-insiders-4.5.0
  2. mkdocs build

Package versions

Configuration

Same as with 8.1.2+insiders.4.54.0, which builds fine.

System information

squidfunk commented 2 years ago

Thanks for reporting. Did you extend the theme? More specifically: did you override base.html? In any case, it would be of great help if you could try to narrow it down and provide a reproducible case if that's possible.

kcgthb commented 2 years ago

Yes, I have overrides for a landing page, main.html (to define the announce block), 404.html and the new copyright partial. But I tried to entirely disable those overrides from mkdocs.yml before reporting, by commenting the theme.custom_dir: value, but building still failed.

I'll try to narrow it down further.

kcgthb commented 2 years ago

I can actually reproduce the build error with a bare bone mkdocs.yml:

site_name: test
docs_dir: src
site_dir: site
theme:
  name: material

and no overrides (I renamed the default overrides directory, in case it was used as a default).

But building still fails :(

$ mkdocs -v  build
DEBUG    -  Loading configuration file: /home/kilian/Work/Web/sherlock/main/mkdocs.yml
DEBUG    -  Loaded theme configuration for 'material' from
            '/home/kilian/.local/lib/python3.9/site-packages/material/mkdocs_theme.yml': {'language': 'en', 'direction': None,
            'features': [], 'palette': {'primary': None, 'accent': None}, 'font': {'text': 'Roboto', 'code': 'Roboto Mono'}, 'icon':
            None, 'favicon': 'assets/images/favicon.png', 'include_search_page': False, 'search_index_only': True,
            'static_templates': ['404.html']}
DEBUG    -  Config value: 'config_file_path' = '/home/kilian/Work/Web/sherlock/main/mkdocs.yml'
DEBUG    -  Config value: 'site_name' = 'test'
DEBUG    -  Config value: 'nav' = None
DEBUG    -  Config value: 'pages' = None
DEBUG    -  Config value: 'site_url' = ''
[...]
DEBUG    -  Copying media file: 'assets/javascripts/lunr/min/lunr.vi.min.js'
DEBUG    -  Copying media file: 'assets/javascripts/lunr/min/lunr.zh.min.js'
DEBUG    -  Copying media file: 'assets/javascripts/lunr/tinyseg.js'
DEBUG    -  Copying media file: 'assets/javascripts/lunr/wordcut.js'
DEBUG    -  Copying media file: 'assets/javascripts/workers/search.2c14e664.min.js'
DEBUG    -  Copying media file: 'assets/stylesheets/main.ad283078.min.css'
DEBUG    -  Copying media file: 'assets/stylesheets/palette.e6a45f82.min.css'
DEBUG    -  Copying media file: 'assets/stylesheets/vendor/mermaid.9c0dc1da.min.css'
DEBUG    -  Building theme template: sitemap.xml
DEBUG    -  Gzipping template: sitemap.xml
DEBUG    -  Building theme template: 404.html
Traceback (most recent call last):
  File "/home/kilian/.local/bin/mkdocs", line 8, in <module>
    sys.exit(cli())
  File "/usr/lib/python3/dist-packages/click/core.py", line 1126, in __call__
    return self.main(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/click/core.py", line 1051, in main
    rv = self.invoke(ctx)
  File "/usr/lib/python3/dist-packages/click/core.py", line 1657, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/lib/python3/dist-packages/click/core.py", line 1393, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/lib/python3/dist-packages/click/core.py", line 752, in invoke
    return __callback(*args, **kwargs)
  File "/home/kilian/.local/lib/python3.9/site-packages/mkdocs/__main__.py", line 187, in build_command
    build.build(config.load_config(**kwargs), dirty=not clean)
  File "/home/kilian/.local/lib/python3.9/site-packages/mkdocs/commands/build.py", line 306, in build
    _build_theme_template(template, env, files, config, nav)
  File "/home/kilian/.local/lib/python3.9/site-packages/mkdocs/commands/build.py", line 111, in _build_theme_template
    output = _build_template(template_name, template, files, config, nav)
  File "/home/kilian/.local/lib/python3.9/site-packages/mkdocs/commands/build.py", line 90, in _build_template
    output = template.render(context)
  File "/usr/lib/python3/dist-packages/jinja2/environment.py", line 1304, in render
    self.environment.handle_exception()
  File "/usr/lib/python3/dist-packages/jinja2/environment.py", line 925, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "/home/kilian/.local/lib/python3.9/site-packages/material/404.html", line 4, in top-level template code
    {% extends "main.html" %}
  File "/home/kilian/.local/lib/python3.9/site-packages/material/main.html", line 4, in top-level template code
    {% extends "base.html" %}
  File "/home/kilian/.local/lib/python3.9/site-packages/material/base.html", line 158, in top-level template code
    {% block site_nav %}
  File "/home/kilian/.local/lib/python3.9/site-packages/material/base.html", line 166, in block 'site_nav'
    {% include "partials/nav.html" %}
  File "/home/kilian/.local/lib/python3.9/site-packages/material/partials/nav.html", line 27, in top-level template code
    {% include "partials/nav-item.html" %}
  File "/home/kilian/.local/lib/python3.9/site-packages/material/partials/nav-item.html", line 101, in top-level template code
    {{ render(nav_item, path, level) }}
  File "/usr/lib/python3/dist-packages/jinja2/runtime.py", line 828, in _invoke
    rv = self._func(*arguments)
  File "/home/kilian/.local/lib/python3.9/site-packages/material/partials/nav-item.html", line 40, in template
    {{ render_content(nav_item) }}
  File "/usr/lib/python3/dist-packages/jinja2/runtime.py", line 828, in _invoke
    rv = self._func(*arguments)
  File "/home/kilian/.local/lib/python3.9/site-packages/material/partials/nav-item.html", line 5, in template
    {% if "icon" in meta[nav_item.url] %}
jinja2.exceptions.UndefinedError: dict object has no element Undefined
kcgthb commented 2 years ago

Ok, I think I have a very minimal reproducer:

  1. create a new blank Mkdocs site
  2. set the theme to Material
  3. build

It can't really get more minimal that this, I guess :)

$ cd $(mktemp -d)
$ mkdocs new .
$ cat << EOF >> mkdocs.yml
theme:
  name: material
EOF

$ mkdocs build
INFO     -  Cleaning site directory
INFO     -  Building documentation to directory: /tmp/tmp.1Xix62WSrm/site
Traceback (most recent call last):
  File "/home/kilian/.local/bin/mkdocs", line 8, in <module>
    sys.exit(cli())
  File "/usr/lib/python3/dist-packages/click/core.py", line 1126, in __call__
    return self.main(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/click/core.py", line 1051, in main
    rv = self.invoke(ctx)
  File "/usr/lib/python3/dist-packages/click/core.py", line 1657, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/lib/python3/dist-packages/click/core.py", line 1393, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/lib/python3/dist-packages/click/core.py", line 752, in invoke
    return __callback(*args, **kwargs)
  File "/home/kilian/.local/lib/python3.9/site-packages/mkdocs/__main__.py", line 187, in build_command
    build.build(config.load_config(**kwargs), dirty=not clean)
  File "/home/kilian/.local/lib/python3.9/site-packages/mkdocs/commands/build.py", line 306, in build
    _build_theme_template(template, env, files, config, nav)
  File "/home/kilian/.local/lib/python3.9/site-packages/mkdocs/commands/build.py", line 111, in _build_theme_template
    output = _build_template(template_name, template, files, config, nav)
  File "/home/kilian/.local/lib/python3.9/site-packages/mkdocs/commands/build.py", line 90, in _build_template
    output = template.render(context)
  File "/usr/lib/python3/dist-packages/jinja2/environment.py", line 1304, in render
    self.environment.handle_exception()
  File "/usr/lib/python3/dist-packages/jinja2/environment.py", line 925, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "/home/kilian/.local/lib/python3.9/site-packages/material/404.html", line 4, in top-level template code
    {% extends "main.html" %}
  File "/home/kilian/.local/lib/python3.9/site-packages/material/main.html", line 4, in top-level template code
    {% extends "base.html" %}
  File "/home/kilian/.local/lib/python3.9/site-packages/material/base.html", line 158, in top-level template code
    {% block site_nav %}
  File "/home/kilian/.local/lib/python3.9/site-packages/material/base.html", line 166, in block 'site_nav'
    {% include "partials/nav.html" %}
  File "/home/kilian/.local/lib/python3.9/site-packages/material/partials/nav.html", line 27, in top-level template code
    {% include "partials/nav-item.html" %}
  File "/home/kilian/.local/lib/python3.9/site-packages/material/partials/nav-item.html", line 101, in top-level template code
    {{ render(nav_item, path, level) }}
  File "/usr/lib/python3/dist-packages/jinja2/runtime.py", line 828, in _invoke
    rv = self._func(*arguments)
  File "/home/kilian/.local/lib/python3.9/site-packages/material/partials/nav-item.html", line 96, in template
    {{ render_content(nav_item) }}
  File "/usr/lib/python3/dist-packages/jinja2/runtime.py", line 828, in _invoke
    rv = self._func(*arguments)
  File "/home/kilian/.local/lib/python3.9/site-packages/material/partials/nav-item.html", line 5, in template
    {% if "icon" in meta[nav_item.url] %}
jinja2.exceptions.UndefinedError: 'dict object' has no attribute ''

And downgrading to 4.4.0 works instantly:

$ pip install --user --upgrade git+https://github.com/squidfunk/mkdocs-material-insiders.git@8.1.2-insiders-4.4.0
[...]
$ mkdocs build
INFO     -  Cleaning site directory
INFO     -  Building documentation to directory: /tmp/tmp.1Xix62WSrm/site
INFO     -  Documentation built in 0.15 seconds
squidfunk commented 2 years ago

Thanks! I'll look into it.

squidfunk commented 2 years ago

I'm not able to reproduce this. Does this still happen when you try the latest master?

kcgthb commented 2 years ago

Yep, same issue with master, installed from a fresh git clone with:

$ git clone https://github.com/squidfunk/mkdocs-material-insiders.git
$ cd mkdocs-material-insiders/
$ pip3 install --user --upgrade .
squidfunk commented 2 years ago

Hmm, weird. master works perfect for me with a new project.

kcgthb commented 2 years ago

Ah ha! I tracked it down to the version of Jinja2 that I had installed, system-wide (Debian provides python3-jinja2 3.0.1):

$  pip3 list -v | grep -i jinja2
Jinja2                     3.0.1                /usr/lib/python3/dist-packages
$ mkdocs build
[...]
    {% if "icon" in meta[nav_item.url] %}
jinja2.exceptions.UndefinedError: 'dict object' has no attribute ''

With Jinja2 3.0.2:

$ pip3 list -v | grep -i jinja2
Jinja2                     3.0.2                /home/kilian/.local/lib/python3.9/site-packages pip
$ mkdocs build
INFO     -  Cleaning site directory
INFO     -  Building documentation to directory: /tmp/tmp.zZSFxZHsUY/site
INFO     -  Documentation built in 0.18 seconds
squidfunk commented 2 years ago

Thanks for digging into this! We depend on Jinja >= 2.11.1, which is very conservative but, since MkDocs is based on Jinja 2.x as well, it's probably not a good idea to bump the version range to >= 3.0.2. For this reason, I'd consider this as an upstream bug, which was immediately fixed in a subsequent release, so no action needs to be taken.