Skip to content

fix: support API v68 <ends> elements in the Flow engine - #515

Draft
nikhil-mittal-165 wants to merge 3 commits into
devfrom
fix/issue-2098-flow-ends-element
Draft

nikhil-mittal-165 wants to merge 3 commits into
devfrom
fix/issue-2098-flow-ends-element

Conversation

@nikhil-mittal-165

Copy link
Copy Markdown
Contributor

Summary

Triage of code-analyzer issue 2098: the Flow engine crashes on flows retrieved with API v68.0, which now store End elements as top-level <ends> tags (Winter '27).

Root Cause

The Flow engine's Python parser does not recognize the API v68 top-level <ends> element. ends is missing from CTRL_FLOW_ELEM in public/parse_utils.py, so connectors that target an End element are reported as "non-traversable". The element-type switch in flow_parser/parse.py also has no ends branch, so it logs "Variable type cannot find match ... with tag ends". The flow scan then exits without writing flowScannerResultsFile.json, and FlowScannerCommandWrapper.ts throws a raw ENOENT that surfaces as an unexpected engine error.

Fix

  • Recognize ends as a control-flow element in parse_utils.py and handle it in parse.py.
  • Add a unit test for the new element in test_parse_utils.py.
  • When the scanner results file is missing, throw a clear error (new message in messages.ts) instead of a raw ENOENT.

Testing

  • ✅ Functional test on a v68 flow with a top-level <ends> element, run through bin/run.js code-analyzer run --rule-selector flow:
    • Original engine: UnexpectedEngineError (ENOENT flowScannerResultsFile.json), bug reproduced.
    • Fixed engine: Found 4 violation(s) across 1 file(s) (flow:MissingDescription), no engine error.
    • Mixed workspace of Dreamhouse flows plus the v68 flow on the fixed branch: the v68 flow scans fine.
  • ⚠️ The full jest and pytest suites were not run to completion in the automated run (default Python 3.9 and missing pytest), so CI results are the real signal here.

Files Changed

  • packages/code-analyzer-flow-engine/FlowScanner/public/parse_utils.py
  • packages/code-analyzer-flow-engine/FlowScanner/flow_parser/parse.py
  • packages/code-analyzer-flow-engine/FlowScanner/tests/test_parse_utils.py
  • packages/code-analyzer-flow-engine/src/messages.ts
  • packages/code-analyzer-flow-engine/src/python/FlowScannerCommandWrapper.ts

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@git2gus

git2gus Bot commented Nov 2, 2026

Copy link
Copy Markdown

Git2Gus App is installed but the .git2gus/config.json doesn't have right values. You should add the required configuration.

@nikhil-mittal-165

Copy link
Copy Markdown
Contributor Author

Self-review using the refreshed Code Analyzer regression-review skill.

Finding

[P2] Preserve non-ENOENT results-file read failures

The new catch converts every readFile failure into “did not produce a results file.” If the scanner created the file but it is unreadable, is a directory, or another filesystem error occurs, the user now gets a false parser diagnosis and loses the original error code/cause. Restrict the friendly message to ENOENT; rethrow or wrap other failures with their cause.

let outputFileContents: string;
try {
outputFileContents = await fs.promises.readFile(flowScannerResultsFile, 'utf-8');
} catch (_err) {
throw new Error(getMessage('ResultsFileNotProduced', absLogFilePath));
}

Manual validation before merge

Required:

  • Run a real API v68 flow containing one top-level End element through the packed engine and CLI. Verify normal violations are produced and no critical engine failure occurs.
  • Run a flow with two independent branches converging on one named End element, matching the issue report. Verify traversal completes without missing/duplicate-element warnings.
  • Scan a mixed workspace containing v67 flows, v68 End elements, and one malformed flow. Verify valid files retain established partial-failure behavior and the surfaced error points to the Flow log.
  • Force both a missing results file and a non-ENOENT read failure. The first should use the new actionable message; the second should retain its actual filesystem cause.

Recommended:

  • Repeat the installed-package scan on Windows because the original issue was reported there.

Evidence checked: linked issue #2098, parser/control-flow call paths, changed tests, packaged wrapper path, and green Linux/macOS/Windows CI. The functional run in the PR description is author-supplied evidence, not independently reproduced here.

Previously every readFile failure on the results file was reported as "the
Flow Scanner did not produce a results file". Now only ENOENT gets that
message; any other failure (permissions, directory, etc.) is reported with a
new ResultsFileNotReadable message and keeps the original error as the cause.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@nikhil-mittal-165

Copy link
Copy Markdown
Contributor Author

Addressed the P2 finding in ef8a7f5: only ENOENT now produces the 'did not produce a results file' message. Other read failures use a new ResultsFileNotReadable message and keep the original error as cause. Added tests for ENOENT, EACCES and EISDIR. The manual validation items are still outstanding.

🤖 Generated with Claude Code

API v68 flows can declare <runInMode>UserMode</runInMode>, which was missing
from the RunMode enum, so RunMode[...] raised KeyError and the scan crashed
(even for flows with no <ends> element). Add UserMode (treated like
DefaultMode, i.e. user context), and make unrecognized runInMode values log a
warning and fall back to DefaultMode instead of crashing the whole scan.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@nikhil-mittal-165

Copy link
Copy Markdown
Contributor Author

Also fixes the second API v68 crash reported alongside this issue: runInMode=UserMode was missing from the RunMode enum, so RunMode[...] raised KeyError and the scan failed even for flows with no <ends> element (9acbd97).

  • Added UserMode to RunMode (treated like DefaultMode, i.e. user context).
  • Unrecognized runInMode values now log a warning and fall back to DefaultMode instead of crashing the whole scan.
  • Added tests/test_run_mode.py (5 tests, which failed before the fix).
  • Verified with a v68 flow that has runInMode=UserMode and no <ends>: before, flow:UnexpectedEngineError; after, the scan completes with normal violations.

🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants