Skip to content

fix: output structured XML errors in subagent mode#1856

Open
mashraf-222 wants to merge 1 commit intomainfrom
fix/structured-error-output-subagent-mode
Open

fix: output structured XML errors in subagent mode#1856
mashraf-222 wants to merge 1 commit intomainfrom
fix/structured-error-output-subagent-mode

Conversation

@mashraf-222
Copy link
Contributor

Summary

  • exit_with_message() now outputs <codeflash-error> XML to stdout in subagent mode instead of Rich panel text
  • Enables the Claude Code plugin agent to parse error messages programmatically

Problem

When codeflash encounters errors in --subagent mode (no git repo, file not found, config errors, etc.), it outputs Rich-formatted panel text. The calling Claude agent expects structured data and may misinterpret or ignore these errors. The success path already outputs structured XML (<codeflash-optimization>, <codeflash-summary>), but the error path didn't.

Root cause

exit_with_message() in code_utils.py is the central error exit function used by ~15 call sites. It had special handling for LSP mode (log instead of exit) but no handling for subagent mode.

Solution

Added a subagent mode check in exit_with_message() that outputs structured XML before exiting:

<codeflash-error>No codeflash configuration found. Run `codeflash init` first.</codeflash-error>

XML special characters are properly escaped via xml.sax.saxutils.escape. This matches the pattern already used by the success output (<codeflash-optimization>) and the no-results output (<codeflash-summary>).

Code changes

  • codeflash/code_utils/code_utils.py: Added is_subagent_mode import and subagent check in exit_with_message() — 4 lines of logic
  • tests/test_code_utils.py: 3 new tests covering structured XML output, XML escaping, and non-subagent mode behavior

Testing

$ uv run pytest tests/test_code_utils.py::TestExitWithMessageSubagent -v
# 3 passed

🤖 Generated with Claude Code

When codeflash runs with --subagent (e.g., via the Claude Code plugin),
exit_with_message() now outputs <codeflash-error> XML to stdout instead
of Rich panel text. This lets the calling agent parse errors
programmatically rather than receiving unstructured text.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@claude
Copy link
Contributor

claude bot commented Mar 17, 2026

Claude finished @mashraf-222's task in 2m 26s —— View job


PR Review Summary

  • Triage: assess PR scope
  • Lint and typecheck changed files
  • Resolve stale review threads (none found)
  • Code review
  • Duplicate detection
  • Test coverage

Prek Checks

✅ All checks passed — ruff check and ruff format both clean.

Mypy shows 29 errors in the two changed files, but these are all pre-existing issues unrelated to this PR. No new type errors were introduced.

Code Review

The implementation is correct and follows the existing patterns in the codebase.

Observations:

  1. Lazy import (from xml.sax.saxutils import escape) — This stdlib module is imported inside the function body. Since it's a stdlib module with negligible import cost, it should be moved to the top-level imports for consistency with the rest of the file. Minor style issue only. Fix this →

  2. error_on_exit=False path — When error_on_exit=False (the default), the subagent path still outputs <codeflash-error> and exits with code 0. This is consistent with the non-subagent path (which always shows a red panel), but it means the calling agent will see <codeflash-error> even when the exit code is 0. The semantics are slightly confusing — callers will need to check both the tag and the exit code. This is probably acceptable given the existing behavior, but worth documenting.

  3. sys.stdout.write vs print — Functionally equivalent; sys.stdout.write is used for consistency since it avoids the trailing newline complexity (the \n is explicit). Fine.

  4. XML escapingxml.sax.saxutils.escape handles <, >, & correctly. Doesn't escape " or ', but those are only significant inside XML attributes, not text content — so this is correct.

  5. Exit code duplication — The sys.exit(1 if error_on_exit else 0) line now appears twice in the function (once for subagent, once for normal mode). This is minor and acceptable for clarity.

No bugs or security issues found.

Duplicate Detection

No duplicates detected. The <codeflash-error> XML tag is new and consistent with <codeflash-optimization> and <codeflash-summary> already used in the success path.

Test Coverage

All 3 new tests pass:

  • test_outputs_structured_xml_in_subagent_mode
  • test_escapes_xml_special_chars
  • test_no_xml_when_not_subagent

Coverage for codeflash/code_utils/code_utils.py: 40% (pre-existing, unchanged).

One minor gap: no test for error_on_exit=False in subagent mode (verifying sys.exit(0) is called). Not blocking.


Overall: Clean implementation, correct behavior, well-tested. The only actionable suggestion is moving the lazy import to the top-level.

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.

1 participant