Python: Fix PowerFx eval crash on non-English system locales by setting CurrentUICulture to en-US#4408
Conversation
On non-English systems, CultureInfo.CurrentUICulture causes PowerFx to
emit localized error messages. The existing ValueError guard only matches
English strings ("isn't recognized", "Name isn't valid"), so undefined
variable errors crash instead of returning None gracefully.
Fix: save and restore CurrentUICulture alongside CurrentCulture before
calling engine.eval(), ensuring error messages are always in English.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
moonbox3
left a comment
There was a problem hiding this comment.
Automated Code Review
Reviewers: 3 | Confidence: 89%
✓ Correctness
The diff correctly saves and restores
CurrentUICulturealongsideCurrentCulturebefore callingengine.eval(), ensuring PowerFx error messages are always in English so the downstream string-matching error handlers work on non-English systems. Thefinallyblock properly restores both culture values even when exceptions propagate to the outerexcept ValueError. The regression test is well-structured and mirrors the existing test patterns. No correctness issues found.
✓ Security Reliability
The diff correctly extends the existing culture save/restore pattern to also cover CurrentUICulture, preventing localized PowerFx error messages from bypassing English string guards. The finally block properly restores both culture values on all exit paths. No new security or reliability issues are introduced; the pre-existing thread-safety concern around mutating global/thread-local culture state is not worsened by this change.
✓ Test Coverage
The diff adds
CurrentUICulturehandling alongsideCurrentCulturein the PowerFx eval path and includes a well-structured regression test that sets a non-English UI culture and verifies undefined variables still returnNone. The test directly exercises the bug scenario. However, there is no assertion verifying thatCurrentUICultureis properly restored aftereval()returns, which is the other half of the production-code change (thefinallyblock). Without that, a regression in the cleanup path would go undetected.
Suggestions
- The mutation of CultureInfo.CurrentCulture and CultureInfo.CurrentUICulture is not thread-safe if multiple threads call eval concurrently. This is a pre-existing concern not introduced by this diff, but worth noting for future hardening (e.g., using a lock around the eval call).
- Add an assertion after
state.eval()to verify thatCurrentUICultureis restored to the pre-eval value (e.g., 'it-IT'). This would cover thefinally-block restoration logic in the production code and catch future regressions in cleanup. - Consider adding a parallel test (or extending this one) that exercises a successful eval (not just the undefined-variable error path) under a non-English UI culture, to confirm the culture-swap works for normal evaluation too.
Automated review by moonbox3's agents
Python Test Coverage Report •
Python Unit Test Overview
|
||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Pull request overview
Fixes a locale-dependent crash in the declarative PowerFx evaluator by ensuring .NET UI culture is forced to English during evaluation, so existing (English) error-string guards behave consistently across non-English systems.
Changes:
- In
DeclarativeWorkflowState.eval(), temporarily setsCultureInfo.CurrentUICulturetoen-USalongsideCurrentCultureand restores both afterward. - Adds a regression test that simulates a non-English UI culture (
it-IT) and verifies undefined variables returnNoneinstead of raising.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| python/packages/declarative/agent_framework_declarative/_workflows/_declarative_base.py | Forces CurrentUICulture to en-US during PowerFx engine.eval() to prevent localized error messages from bypassing the undefined-variable guard. |
| python/packages/declarative/tests/test_powerfx_yaml_compatibility.py | Adds a regression test for non-English UI cultures to ensure undefined variable references are handled gracefully. |
python/packages/declarative/agent_framework_declarative/_workflows/_declarative_base.py
Outdated
Show resolved
Hide resolved
Cache CultureInfo("en-US") in a local variable instead of instantiating
it twice per eval() call, as suggested in PR review.
Fixes microsoft#4321
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assert that the production code's finally-block correctly restores CurrentUICulture to it-IT after eval returns, covering future regressions where the culture could leak. The CultureInfo caching suggestion (comment #2) was already implemented in the production code. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Motivation and Context
On non-English system locales, PowerFx emits localized error messages for undefined variables (e.g., Italian instead of English). The existing error-handling guards only match English strings like "isn't recognized" and "Name isn't valid", so localized messages fall through and crash the workflow.
Fixes #4321
Description
The root cause is that
CurrentUICulturecontrols the language of .NET error messages, but onlyCurrentCulturewas being set toen-USbefore callingengine.eval. This fix saves and overridesCurrentUICulturetoen-USalongsideCurrentCulture, ensuring PowerFx error messages are always in English and match the existing string guards. Both cultures are restored in thefinallyblock. A regression test simulates a non-English UI culture (it-IT) and verifies that undefined variable references returnNoneinstead of raising.Contribution Checklist