Skip to content

flow engine fails on Windows for any flow containing a non-ASCII character (cp1252 UnicodeDecodeError surfaced as ENOENT UnexpectedEngineError) #2074

Description

@rob-alexa

Bug Description

On Windows, the flow engine fails for any workspace containing a flow whose XML has a character outside cp1252. It surfaces as a Critical UnexpectedEngineError about a missing temp file, so nothing in the reported error points at the real cause.

quick_validate in FlowScanner/public/parse_utils.py opens each flow file and calls fp.read() without passing encoding. Python then falls back to the locale encoding, which on Windows is cp1252, so any flow containing a character that cp1252 cannot decode raises UnicodeDecodeError. The scanner logs each failure at CRITICAL and drops that flow. When no flow survives, it exits with No flow files found to scan. Exiting... and never writes the --json results file. FlowScannerCommandWrapper.runFlowScannerRules then fails reading that file.

A single curly quote is enough to trigger it. The first failing byte in our case is 0x9D, which is the third byte of U+201D RIGHT DOUBLE QUOTATION MARK (E2 80 9D) and is undefined in cp1252. Smart quotes are common in flow screen text, error messages and descriptions, so this is easy to hit on a real project.

This is a locale issue rather than a Python version issue. Python 3.11 on Windows fails the same way. Linux is unaffected because the locale there is already UTF-8, which is why this never appears in GitHub Actions.

Setting PYTHONUTF8=1 makes the identical command succeed, which confirms the cause.

Output / Logs

What the user sees:

Found 1 violation(s) across 0 file(s):
    1 Critical severity violation(s) found.

UnexpectedEngineError: The engine with name 'flow' threw an unexpected error:
Error: ENOENT: no such file or directory, open
'C:\Users\<user>\AppData\Local\Temp\code-analyzer-XXXXXX\run-XXXX\flow\flowScannerResultsFile.json'
    at async RunTimeFlowScannerCommandWrapper.runFlowScannerRules
       (...\@salesforce\code-analyzer-flow-engine\dist\python\FlowScannerCommandWrapper.js:52:36)
    at async FlowScannerEngine.runRules (...\code-analyzer-flow-engine\dist\engine.js:104:34)

The actual cause, visible only when the bundled scanner is run directly:

CRITICAL | could not quick_validate flow <repo>\force-app\main\default\flows\<flow>.flow-meta.xml
Traceback (most recent call last):
  File "...\@salesforce\code-analyzer-flow-engine\FlowScanner\public\parse_utils.py", line 1419, in quick_validate
    flow_data = fp.read()
  File "...\Python\Python314\Lib\encodings\cp1252.py", line 23, in decode
    return codecs.charmap_decode(input,self.errors,decoding_table)[0]
UnicodeDecodeError: 'charmap' codec can't decode byte 0x9d in position 7212: character maps to <undefined>

**STATUS: Discovering flows**
No flow files found to scan. Exiting...

Steps To Reproduce

  1. Use a Windows machine with a non-UTF-8 locale (a standard en-US install, cp1252).
  2. Create or take any flow whose XML contains a character outside cp1252. A curly quote in screen text or an error message is enough, for example an <errorMessage> containing U+201D.
  3. Run sf code-analyzer run --rule-selector flow --target path/to/that.flow-meta.xml.
  4. The run ends with a Critical UnexpectedEngineError naming a missing flowScannerResultsFile.json, and no flow rules are evaluated.

To see the underlying error, invoke the bundled scanner directly from the engine folder:

cd <sf-plugins>/node_modules/@salesforce/code-analyzer-flow-engine/FlowScanner
python -m flow_scanner --debug --log_file log.txt \
  --workspace workspaceFiles.txt --target targetedFiles.txt \
  --queries <queryName> --json out.json

Re-running that exact command with PYTHONUTF8=1 set succeeds and writes the results file.

Expected Behavior

Flow files should be read as UTF-8 regardless of platform locale. The Metadata API writes flow XML as UTF-8 and the files themselves declare <?xml version="1.0" encoding="UTF-8"?>, so the encoding is not ambiguous.

Suggested fix: pass the encoding explicitly wherever flow source is read, for example open(path, encoding='utf-8') in quick_validate and anywhere else the scanner reads flow XML.

A second, smaller point: when no flow survives validation, the engine exits without writing the results file, so a decoding problem reaches the user as a missing-file error from the Node wrapper. Failing with the collected validation errors instead would make this class of problem self-diagnosing.

Operating System

Windows 11 Enterprise 10.0.26200

Salesforce CLI Version

@salesforce/cli/2.144.6 win32-x64 node-v24.18.0

Code Analyzer Plugin (code-analyzer) Version

5.14.0 (bundled @salesforce/code-analyzer-flow-engine 0.38.0)

Node Version

v24.18.0

Java Version

Not relevant to this engine; the failure is in the Python flow scanner.


Workaround for other Windows users until this is fixed: set PYTHONUTF8=1 in the environment before running sf code-analyzer run.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions