Skip to content

fix(execute_code): skip phantom CodeDom BOM error from mcs compiler#1250

Open
beast-ofcourse wants to merge 1 commit into
CoplayDev:betafrom
beast-ofcourse:fix/execute-code-bom-phantom-error
Open

fix(execute_code): skip phantom CodeDom BOM error from mcs compiler#1250
beast-ofcourse wants to merge 1 commit into
CoplayDev:betafrom
beast-ofcourse:fix/execute-code-bom-phantom-error

Conversation

@beast-ofcourse

@beast-ofcourse beast-ofcourse commented Jul 7, 2026

Copy link
Copy Markdown

Problem

The \execute_code\ tool consistently fails with a phantom compilation error when using the CodeDom compiler on Mono/Windows. The error reports a lone U+FEFF (BOM) character on line 1, even though compilation actually succeeds (mcs exits 0 and writes the output DLL).

Fixes #1186

Root Cause

Mono's \mcs\ compiler prints a stray U+FEFF BOM character on stdout during compilation. Mono's CodeDom implementation (\CSharpCodeProvider) can't parse this as a standard compiler error format (\ ile(line,col): error CSxxxx), so it fabricates a \CompilerError\ with:

  • No \ErrorNumber\ (empty string)
  • \ErrorText\ containing only the BOM character
  • \IsWarning\ = false

This causes
esults.Errors.HasErrors\ to return \ rue\ and
esults.CompiledAssembly\ to be
ull\ — even though mcs compiled successfully. The tool reports a failure for a build that was actually fine.

Solution

Three changes to the \CodeDomCompile\ method:

  1. Compile to a temp DLL path instead of in-memory (\GenerateInMemory=false\ + \OutputAssembly). This bypasses CodeDom's refusal to surface the assembly when it thinks there are errors.

  2. Skip phantom BOM errors — errors where \ErrorNumber\ is empty and \ErrorText\ is only BOM/whitespace are benign and should not block execution.

  3. Load the DLL manually — when no real errors exist, load the produced DLL via \Assembly.Load(File.ReadAllBytes(...))\ and clean up the temp file in a \ inally\ block.

Verification

  • Compilation that previously failed with the BOM phantom error now succeeds.
  • Real compilation errors (syntax errors, type mismatches) are still correctly reported.
  • Temp DLL files are cleaned up after loading.
  • Both \On Error Resume Next\ (continue on warning/BOM) and the original \HasErrors\ guard are replaced with explicit real-error detection.

Notes

  • Community member @lgarczyn diagnosed the root cause and provided the candidate fix in the issue comments. This PR applies that fix to the latest \�eta\ branch with minor adjustments.
  • The
    esponseFilePath\ cleanup (existing pattern) is unaffected — both temp files (RSP and DLL) are cleaned up in their respective \ inally\ blocks.

Summary by CodeRabbit

  • Bug Fixes
    • Improved code execution reliability when compiling scripts, reducing false compiler errors caused by stray formatting characters.
    • Added safer handling for compiled output so successful runs are loaded more consistently.
    • Cleaned up temporary compilation files automatically after use.

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 23d5c787-7eda-4bb7-ae43-04b39d975ab1

📥 Commits

Reviewing files that changed from the base of the PR and between bfb743c and 127315b.

📒 Files selected for processing (1)
  • MCPForUnity/Editor/Tools/ExecuteCode.cs
🚧 Files skipped from review as they are similar to previous changes (1)
  • MCPForUnity/Editor/Tools/ExecuteCode.cs

📝 Walkthrough

Walkthrough

The CodeDomCompile method in ExecuteCode.cs was changed to compile user code to a temporary DLL on disk instead of in-memory. It filters out bogus BOM/whitespace-only compiler errors during error collection, verifies the output DLL exists, loads the assembly from disk, and deletes the temp DLL afterward.

Changes

ExecuteCode compilation fix

Layer / File(s) Summary
CodeDom disk-based compile with BOM error filtering
MCPForUnity/Editor/Tools/ExecuteCode.cs
CodeDomCompile switches from in-memory (GenerateInMemory=true) to on-disk compilation with a unique temp DLL output, replaces the HasErrors check with custom error iteration that ignores warnings and skips bogus BOM/whitespace-only errors, verifies the DLL exists, loads the assembly via Assembly.Load(File.ReadAllBytes(...)), and deletes the temp DLL in a finally block.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant CodeDomCompile
  participant CodeDomProvider
  participant FileSystem

  Caller->>CodeDomCompile: invoke with user code
  CodeDomCompile->>CodeDomProvider: compile to temp DLL path
  CodeDomProvider-->>CodeDomCompile: CompilerResults with errors/warnings
  CodeDomCompile->>CodeDomCompile: filter bogus BOM/whitespace errors
  alt non-bogus errors remain
    CodeDomCompile-->>Caller: return null
  else no real errors
    CodeDomCompile->>FileSystem: verify DLL exists
    CodeDomCompile->>FileSystem: read DLL bytes
    CodeDomCompile->>CodeDomCompile: Assembly.Load(bytes)
    CodeDomCompile->>FileSystem: delete temp DLL
    CodeDomCompile-->>Caller: return loaded assembly
  end
Loading

Possibly related PRs

  • CoplayDev/unity-mcp#1170: Also modifies ExecuteCode.CodeDomCompile in the same file to change how CodeDom compilation is invoked and configured.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is specific and matches the main fix: handling the phantom CodeDom BOM error in execute_code.
Description check ✅ Passed The description covers the problem, root cause, solution, and verification, with most template sections addressed or reasonably implied.
Linked Issues check ✅ Passed The PR resolves #1186 by making execute_code succeed despite a leading BOM or phantom BOM-only CodeDom error.
Out of Scope Changes check ✅ Passed The changes stay focused on the BOM/CodeDom failure fix and do not introduce unrelated scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
MCPForUnity/Editor/Tools/ExecuteCode.cs (1)

297-349: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Solid fix for the phantom mcs BOM error; consider extracting the filter for readability.

The disk-based compile, BOM/whitespace error filtering, and load-then-cleanup sequence are correct — Assembly.Load reads bytes into memory first, so deleting the temp DLL in finally (Lines 344-348) won't race with a file lock. Given the flagged complexity of this block, consider pulling the per-error bogus-check (Lines 323-326) into a small named helper (e.g. IsBogusBomError(CompilerError)) to make the filtering intent self-documenting and independently testable.

♻️ Optional extraction
+        private static bool IsBogusBomError(CompilerError error)
+        {
+            string text = (error.ErrorText ?? "").Trim('\uFEFF', ' ', '\t', '\r', '\n');
+            return string.IsNullOrEmpty(error.ErrorNumber) && string.IsNullOrEmpty(text);
+        }
+
         bool hasRealErrors = false;
         foreach (CompilerError error in results.Errors)
         {
             if (error.IsWarning)
                 continue;
 
-            // The bogus BOM "error": no error number, text is just the BOM/whitespace.
-            string text = (error.ErrorText ?? "").Trim('\uFEFF', ' ', '\t', '\r', '\n');
-            if (string.IsNullOrEmpty(error.ErrorNumber) && string.IsNullOrEmpty(text))
+            if (IsBogusBomError(error))
                 continue;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@MCPForUnity/Editor/Tools/ExecuteCode.cs` around lines 297 - 349, The
compile-and-filter logic in ExecuteCode is correct, but the BOM/whitespace
bogus-error check is too inline and hard to read. Extract the per-error filter
used inside the CompilerError loop into a small helper such as
IsBogusBomError(CompilerError) and use it from the CompileAssemblyFromSource
results handling, so the intent is self-documenting and easier to test without
changing the load-and-cleanup flow.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@AGENTS.md`:
- Around line 45-54: The PR creation example is hardcoded with a specific fork
username, which makes the generic workflow misleading. Update the gh pr create
example in AGENTS.md to use a placeholder or generic head format instead of
beast-ofcourse:fix/your-fix, keeping the rest of the command structure intact so
any contributor can substitute their own fork name.

---

Nitpick comments:
In `@MCPForUnity/Editor/Tools/ExecuteCode.cs`:
- Around line 297-349: The compile-and-filter logic in ExecuteCode is correct,
but the BOM/whitespace bogus-error check is too inline and hard to read. Extract
the per-error filter used inside the CompilerError loop into a small helper such
as IsBogusBomError(CompilerError) and use it from the CompileAssemblyFromSource
results handling, so the intent is self-documenting and easier to test without
changing the load-and-cleanup flow.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e4e8a498-a425-44e4-9368-1def2f658451

📥 Commits

Reviewing files that changed from the base of the PR and between 484937c and 1f396f9.

📒 Files selected for processing (2)
  • AGENTS.md
  • MCPForUnity/Editor/Tools/ExecuteCode.cs

Comment thread AGENTS.md Outdated
Comment on lines +45 to +54
```bash
git push origin fix/your-fix
gh pr create \
--repo CoplayDev/unity-mcp \
--base beta \
--head beast-ofcourse:fix/your-fix \
--title "[<area>]: <short description>" \
--body "<body>" \
--label bug
```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Hardcoded fork username in the generic PR-creation example.

--head beast-ofcourse:fix/your-fix bakes in a specific contributor's GitHub handle. As a general workflow guide for any AI agent/contributor, this example will mislead anyone else following it verbatim.

✏️ Suggested fix
 gh pr create \
   --repo CoplayDev/unity-mcp \
   --base beta \
-  --head beast-ofcourse:fix/your-fix \
+  --head <your-github-username>:fix/your-fix \
   --title "[<area>]: <short description>" \
   --body "<body>" \
   --label bug
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
```bash
git push origin fix/your-fix
gh pr create \
--repo CoplayDev/unity-mcp \
--base beta \
--head beast-ofcourse:fix/your-fix \
--title "[<area>]: <short description>" \
--body "<body>" \
--label bug
```
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@AGENTS.md` around lines 45 - 54, The PR creation example is hardcoded with a
specific fork username, which makes the generic workflow misleading. Update the
gh pr create example in AGENTS.md to use a placeholder or generic head format
instead of beast-ofcourse:fix/your-fix, keeping the rest of the command
structure intact so any contributor can substitute their own fork name.

@beast-ofcourse beast-ofcourse force-pushed the fix/execute-code-bom-phantom-error branch from bfb743c to 1f396f9 Compare July 7, 2026 06:26
Mono's mcs compiler emits a stray U+FEFF BOM character on stdout during
compilation. CodeDom's CSharpCodeProvider misinterprets this as a compiler
error (no ErrorNumber, ErrorText is just the BOM), causing HasErrors to be
true and results.CompiledAssembly to be null — even though mcs exits 0 and
wrote the DLL successfully.

Fix:
- Compile to a temp DLL path (GenerateInMemory=false + OutputAssembly)
  instead of relying on results.CompiledAssembly.
- Skip phantom errors where ErrorNumber is empty and ErrorText is only
  BOM/whitespace.
- Load the produced DLL via Assembly.Load(File.ReadAllBytes(...)) when
  no real errors exist.
- Clean up the temp DLL in a finally block.

Fixes CoplayDev#1186
@beast-ofcourse beast-ofcourse force-pushed the fix/execute-code-bom-phantom-error branch from 1f396f9 to 127315b Compare July 7, 2026 06:28
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.

[Bug]: execute_code tool fails with BOM character (U+FEFF) in code parameter

1 participant