sqlalchemy/alembic · error · CommandError

Template rendering failed; see

Error message

Template rendering failed; see %s for a template-oriented traceback.

What it means

Raised as CommandError by template_to_file when Mako template rendering fails (pyfiles.py:31-44). The function catches ALL exceptions from template.render_unicode(), writes a detailed Mako-specific traceback to a temporary .txt file, and raises CommandError pointing to that file. The temp file traceback is essential because Mako errors in the original traceback are often opaque. This is used during 'alembic init' to scaffold migration scripts and env.py from templates.

Solutions

  1. Open the temp file path mentioned in the error message to read the Mako-oriented traceback — it pinpoints the exact template line.
  2. If using a custom template (script_template.mako), validate its Mako syntax: check ${}, % directives, and <%block> tags.
  3. Ensure all template variables referenced in the template are provided by Alembic's init command.
  4. If using the default bundled template, verify the Alembic installation isn't corrupted: pip install --force-reinstall alembic.
  5. Check the output_encoding argument matches the template's actual encoding.

Example fix

# before: custom script_template.mako has an undefined variable
## file: my_template.mako
revision = '${revision_id}'
down_revision = '${undefined_var}'  # Mako error

# after
revision = '${revision_id}'
down_revision = ${repr(down_revision)}
Defensive patterns

Strategy: try-catch

Validate before calling

def validate_mako_template(template_path):
    from mako.template import Template
    try:
        t = Template(filename=template_path)
        # attempt a dry render with dummy vars
        return True
    except Exception:
        return False

Try / catch

from alembic.util.exc import CommandError

try:
    command.init(config, directory)
except CommandError as e:
    if 'Template rendering failed' in str(e):
        # extract temp file path from error and read the Mako traceback
        import re
        match = re.search(r'see (.+\.txt) for', str(e))
        if match:
            with open(match.group(1)) as f:
                print(f.read())
    raise

Prevention

When it happens

Trigger: Calling alembic init (which calls template_to_file at command.py) when the Mako template contains syntax errors, references undefined variables, or has broken control flow. Also triggered by custom templates with incorrect ${} expressions or <%block> directives. The bare 'except:' at pyfiles.py:33 catches everything including Mako exceptions.

Common situations: Using a custom script_template.mako with Mako syntax errors. Template variables expected by the template aren't passed during init. Upgrading Alembic where the bundled template changed but a cached/custom template is stale. Encoding mismatches in the template file.

Related errors


AI-assisted analysis of sqlalchemy/alembic@5551b5d35f (2026-08-11). Data as JSON: /api/errors/e29d1d4a19dc69f0. Report an issue: GitHub.

Appendix: source

Thrown at alembic/util/pyfiles.py:41

    template_file: str | os.PathLike[str],
    dest: str | os.PathLike[str],
    output_encoding: str,
    *,
    append_with_newlines: bool = False,
    **kw: Any,
) -> None:
    template = Template(filename=_preserving_path_as_str(template_file))
    try:
        output = template.render_unicode(**kw).encode(output_encoding)
    except:
        with tempfile.NamedTemporaryFile(suffix=".txt", delete=False) as ntf:
            ntf.write(
                exceptions.text_error_template()
                .render_unicode()
                .encode(output_encoding)
            )
            fname = ntf.name
        raise CommandError(
            "Template rendering failed; see %s for a "
            "template-oriented traceback." % fname
        )
    else:
        with open(dest, "ab" if append_with_newlines else "wb") as f:
            if append_with_newlines:
                f.write("\n\n".encode(output_encoding))
            f.write(output)


def coerce_resource_to_filename(fname_or_resource: str) -> pathlib.Path:
    """Interpret a filename as either a filesystem location or as a package
    resource.

    Names that are non absolute paths and contain a colon
    are interpreted as resources and coerced to a file location.

    """

View on GitHub (pinned to 5551b5d35f)