Skip to content

[6.x]: Windows Path Resolution Bug in TwigEngine causes Unable to find the template for CP routes #18804

@liakosbeupset

Description

@liakosbeupset

What happened?

Description

When running the Craft CMS 6 Alpha on a Windows development environment (like Laragon, XAMPP, or Herd for Windows), navigating to any Control Panel route (such as /admin/login) results in a TemplateLoaderException stating Unable to find the template.

The issue stems from CraftCms\Cms\View\TwigEngine::get(). The engine attempts to extract the relative template name from the absolute file path by stripping out the base templates path. On Windows, $path (provided by Laravel's View Factory) and the result of TemplateMode::get()->templatesPath() often have mismatched directory separators (forward slashes vs. backslashes) or mismatched drive letter casing (C: vs c:). Because TemplateMode::get()->templatesPath() is not normalized before being passed to Str::after, the string extraction silently fails, keeping the full absolute path. The absolute path gets passed into the Twig loader, which prepends the base path again, causing the file lookup to fail.

Steps to reproduce

  1. Set up a local development environment on Windows (e.g., Laragon).
  2. Install Craft CMS 6 Alpha.
  3. Attempt to visit any Control Panel route that renders a Twig template, such as /admin/login.
  4. The application crashes with a TemplateLoaderException looking for an impossible, recursively nested absolute path (e.g., C:\...\templates\C:\...\templates\login.twig).

Expected behavior

The TwigEngine should correctly normalize paths regardless of the OS directory separators and drive letter casing. The relative template name should be successfully extracted, and the Control Panel page should render normally without throwing a TemplateLoaderException.

Actual behavior

A 500 Internal Server Error is thrown with the following exception:

CraftCms\Cms\Twig\Exceptions\TemplateLoaderException
Unable to find the template "C:\...\vendor\craftcms\cms\resources\templates\login.twig".

Even though the file physically exists at that exact path, the Twig loader fails to resolve it due to the un-normalized paths in TwigEngine::get().

Proposed Fix (vendor/craftcms/cms/src/View/TwigEngine.php):

    public function get($path, array $data = []): string
    {
        $normalizedPath = \CraftCms\Cms\Support\File::normalizePath($path);
        $normalizedTemplatesPath = \CraftCms\Cms\Support\File::normalizePath(\CraftCms\Cms\View\TemplateMode::get()->templatesPath());

        $template = \Illuminate\Support\Str::after($normalizedPath, $normalizedTemplatesPath);

        // Fallback for Windows where drive letter casing might differ (C: vs c:)
        if ($template === $normalizedPath) {
            $template = \Illuminate\Support\Str::after(strtolower($normalizedPath), strtolower($normalizedTemplatesPath));
        }

        try {
            return $this->renderer->renderPageTemplate($template, $data);
            // ...

Craft CMS version

6.0.0

PHP version

8.5.6

Operating system and version

Microsoft Windows 10 Pro (Version 10.0.19045)

Database type and version

MySQL 8.4.3

Image driver and version

No response

Installed plugins and versions

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions