Repository: conan-io/conan
Pull request: improve jinja2 failure error messages
Changelog: Fix: Improve error message when ``jinja2`` profile rendering fails due to unexpected syntax.
Docs: Omit

Close https://github.com/conan-io/conan/issues/17932

Problem statement:
[bug] unclear message about error in profile
### Describe the bug

macOS, Conan 2.13, Python 3.13

I have a chain of profiles that are included in one another, one of the base profiles uses Jinja features (variables, comments). Looks like I made a mistake in one of Jinja expressions, but Conan's error doesn't help me tracking it down at all:

> ERROR: Error reading 'CI/conan/ios-arm64' profile: Error reading 'base/ios' profile: Error reading 'apple' profile: Error parsing the profile text file: unexpected char '#' at 4414

The include chain is: ios-arm64 -> ios -> apple -> common, the error definitely comes from `common` as others don't use Jinja features.

I've figured out the source of the error on my own, but Conan should provide clearer message, like which file the error is coming from exactly as well as line number (optionally - column number).

P.S. Adding `-vvv` only shows python backtrace, but that doesn't help much.

### How to reproduce it

Make a Jinja error in profile and run `conan install`

Hints from issue discussion:
Thanks for your feedback @kambala-decapitator 

Could you please provide a ``common`` profile file that triggers that error? (I guess the rest should be relatively easy to replicate, just with profiles with ``include(ios) -> include(apple) -> include(common)`` isn't it?
> (I guess the rest should be relatively easy to replicate, just with profiles with include(ios) -> include(apple) -> include(common) isn't it?

correct. Includes shouldn't even matter.

just reproduced in a very basic case by adding "bad" Jinja expression to my default profile:
```
[settings]
arch=x86_64
build_type=Release
compiler=apple-clang
compiler.cppstd=gnu17
compiler.libcxx=libc++
compiler.version=16
os=Macos

[platform_tool_requires]
cmake/3.31.0
ninja/1.12.1

{% set arr = [
    {# comment that triggers the error #}
    'smth'
] %}
```

and on `conan install` (this profile was passed as **build**) I got stacktrace and error

> ERROR: unexpected char '#' at 210

but if I put this "bad" Jinja expression in a file that's included by this profile, then the stacktrace isn't printed and the error is

> ERROR: Error reading 'default' profile: Error parsing the profile text file: unexpected char '#' at 20

that is,

```
include(1)
[settings]
arch=x86_64
build_type=Release
compiler=apple-clang
compiler.cppstd=gnu17
compiler.libcxx=libc++
compiler.version=16
os=Macos

[platform_tool_requires]
cmake/3.31.0
ninja/1.12.1
```

Commit message: improve jinja2 failure error messages

Patch to review:
diff --git a/conan/__init__.py b/conan/__init__.py
index 64d0beef500..f889dbda6f2 100644
--- a/conan/__init__.py
+++ b/conan/__init__.py
@@ -2,5 +2,5 @@
 from conan.internal.model.workspace import Workspace
 from conan.internal.model.version import Version
 
-__version__ = '2.14.0-dev'
+__version__ = '2.15.0-dev'
 conan_version = Version(__version__)
diff --git a/conan/internal/api/profile/profile_loader.py b/conan/internal/api/profile/profile_loader.py
index 5ed77b1f17a..ddc19bb6486 100644
--- a/conan/internal/api/profile/profile_loader.py
+++ b/conan/internal/api/profile/profile_loader.py
@@ -126,9 +126,9 @@ def _load_profile(self, profile_name, cwd):
         # Always include the root Conan home "profiles" folder as secondary route for loading
         # imports and includes from jinja2 templates.
         loader_paths = [base_path, profiles_folder]
-        rtemplate = Environment(loader=FileSystemLoader(loader_paths)).from_string(text)
 
         try:
+            rtemplate = Environment(loader=FileSystemLoader(loader_paths)).from_string(text)
             text = rtemplate.render(context)
         except Exception as e:
             raise ConanException(f"Error while rendering the profile template file '{profile_path}'. "
diff --git a/test/integration/configuration/test_profile_jinja.py b/test/integration/configuration/test_profile_jinja.py
index dc3d3daf340..d8af563a135 100644
--- a/test/integration/configuration/test_profile_jinja.py
+++ b/test/integration/configuration/test_profile_jinja.py
@@ -266,9 +266,39 @@ def test_profile_detect_compiler_missing_error(self):
 
 def test_profile_jinja_error():
     c = TestClient(light=True)
-    c.save({"profile1": "{% set kk = other() %}"})
+    profile = textwrap.dedent("""
+        {% set arr = [
+            {# comment that triggers the error #}
+            'smth'
+        ] %}""")
+    c.save({"profile1": profile,
+            "profile2": "include(profile1)",
+            "profile3": "include(profile2)",
+            "conanfile.txt": ""})
     c.run("profile show -pr=profile1", assert_error=True)
     assert "ERROR: Error while rendering the profile template file" in c.out
+    c.run("profile show -pr=profile2", assert_error=True)
+    assert "ERROR: Error reading 'profile2' profile: Error while " \
+           "rendering the profile template file " in c.out
+    assert "unexpected char '#' at 21" in c.out
+    c.run("profile show -pr=profile3", assert_error=True)
+    assert "ERROR: Error reading 'profile3' profile: Error reading 'profile2' profile: Error while " \
+           "rendering the profile template file " in c.out
+    assert "unexpected char '#' at 21" in c.out
+
+    # Also install messages
+    c.run("install . -pr=profile1", assert_error=True)
+    assert "ERROR: Error while rendering the profile template file" in c.out
+    assert "unexpected char '#' at 21" in c.out
+
+    c.run("install . -pr=profile2", assert_error=True)
+    assert "ERROR: Error reading 'profile2' profile: Error while " \
+           "rendering the profile template file " in c.out
+    assert "unexpected char '#' at 21" in c.out
+    c.run("install . -pr=profile3", assert_error=True)
+    assert "ERROR: Error reading 'profile3' profile: Error reading 'profile2' profile: Error while " \
+           "rendering the profile template file " in c.out
+    assert "unexpected char '#' at 21" in c.out
 
 
 def test_profile_macro_per_package():


Code review comments:
diff_hunk: @@ -2,5 +2,5 @@
 from conan.internal.model.workspace import Workspace
 from conan.internal.model.version import Version
 
-__version__ = '2.14.0-dev'
+__version__ = '2.15.0-dev'
path: conan/__init__.py
text: @user1:
```suggestion
__version__ = '2.14.0'
```