Skip to content

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

Merged
Scriptwonder merged 1 commit into
CoplayDev:betafrom
beast-ofcourse:fix/execute-code-bom-phantom-error
Aug 2, 2026
Merged

fix(execute_code): skip phantom CodeDom BOM error from mcs compiler#1250
Scriptwonder merged 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
@Scriptwonder Scriptwonder added the safe-to-test Triggers CI checks label Aug 2, 2026
@Scriptwonder
Scriptwonder merged commit 8bf889c into CoplayDev:beta Aug 2, 2026
5 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

safe-to-test Triggers CI checks

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

2 participants