Skip to content

fix(workflow): tolerate absent upstream jinja2 variables in LLM nodes (#38655) - #39166

Closed
natemiller23 wants to merge 1 commit into
langgenius:mainfrom
natemiller23:fix/openjobs-38655-langgenius-dify-fix-issue-38655-missing-variable
Closed

fix(workflow): tolerate absent upstream jinja2 variables in LLM nodes (#38655)#39166
natemiller23 wants to merge 1 commit into
langgenius:mainfrom
natemiller23:fix/openjobs-38655-langgenius-dify-fix-issue-38655-missing-variable

Conversation

@natemiller23

Copy link
Copy Markdown

Summary

Fixes #38655 — when a conditional branch feeds an LLM node whose Jinja2 template guards an optional upstream variable with {% if var is defined and var %}, Dify crashed before template evaluation with Variable <name> not found.

The crash originated in graphon's LLMNode._fetch_jinja_inputs, which raised VariableNotFoundError for every entry in prompt_config.jinja2_variables whose upstream selector was missing from the variable pool. graphon's own renderer (_render_jinja2_message) already treats a missing variable as an empty string, so the strict pre-check was the only thing failing.

Fix

Patch graphon's LLMNode._fetch_jinja_inputs at node-registration time (register_nodes in api/core/workflow/node_factory.py) so an absent upstream jinja2 variable is tolerated and skipped instead of raising. The user-authored is defined guard now decides whether the branch renders — exactly as the issue requests.

  • graphon is an external pinned dependency (graphon==0.6.0), so we monkey-patch the live class once at registration time rather than fork the package.
  • Prompt-template inputs, context and memory paths are unchanged (still required).
  • The patch is idempotent (guarded by a marker attribute).

Testing notes

Unit tests added / updated:

  • api/tests/unit_tests/core/workflow/test_node_factory.py::TestJinjaMissingVariableTolerance
    • test_absent_jinja_variable_is_tolerated: absent jinja2 variable no longer raises VariableNotFoundError; present variables still collected.
    • test_only_present_variables_collected: only present upstream variables are returned in the jinja input mapping.
  • api/tests/unit_tests/core/workflow/nodes/llm/test_node.py
    • Updated test_fetch_jinja_inputs_raises_for_missing_variable -> test_fetch_jinja_inputs_tolerates_missing_variable to assert the new intended behavior (returns {} instead of raising).

Run with:

uv run --project api --python 3.12 --no-default-groups --group dev --group storage --group tools --group trace-all pytest api/tests/unit_tests/core/workflow/test_node_factory.py::TestJinjaMissingVariableTolerance api/tests/unit_tests/core/workflow/nodes/llm/test_node.py -k jinja -q

Result: all green (the regression suite for the LLM node jinja path passes).

OpenJobs

Refs: #38655

…langgenius#38655)

When a conditional branch feeds an LLM node whose Jinja2 template guards an
optional upstream variable with `{% if var is defined and var %}`, Dify crashed
before template evaluation with 'Variable <name> not found'.

The crash originated in graphon's LLMNode._fetch_jinja_inputs, which raised
VariableNotFoundError for every entry in prompt_config.jinja2_variables whose
upstream selector was missing from the variable pool. graphon's own renderer
already treats a missing variable as an empty string, so the strict pre-check
was the only thing failing.

Patch graphon's LLMNode._fetch_jinja_inputs at node-registration time
(register_nodes) so an absent upstream jinja2 variable is tolerated and skipped
instead of raising. User-authored 'is defined' guards now decide whether the
branch renders, exactly as the issue requests.

- graphon is an external pinned dependency (graphon==0.6.0), so we monkey-patch
  the live class once rather than fork the package.
- Prompt-template inputs, context and memory paths are unchanged (still required).

Refs: langgenius#38655
OpenJobs: openjobs.bot | https://openjobs.bot/jobs/b13fc23b-8eff-477a-afa3-79bdcd77f665 | b13fc23b-8eff-477a-afa3-79bdcd77f665
@dosubot dosubot Bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Jul 17, 2026
@crazywoola

Copy link
Copy Markdown
Member

Hi @natemiller23, thanks for opening this pull request.

Why this is being closed

Issue #38655 has multiple open pull requests. Under the duplicate-PR rule, pull requests from the issue author are ranked first, then creation time is used as the FIFO tie-breaker. PR #39153 is the retained pull request, so this one is being closed.

Next steps

Please coordinate on PR #39153 if you would like to contribute further. Thank you for understanding.

@crazywoola crazywoola closed this Jul 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

When using conditional branches (if) and Jinja2 templates in combination, Dify may fail directly if the dependent variable does not exist.

2 participants