Skip to content

fix: distinguish Blender addon errors from transport failures#228

Open
obselate wants to merge 1 commit into
ahujasid:mainfrom
obselate:fix/distinguish-blender-errors
Open

fix: distinguish Blender addon errors from transport failures#228
obselate wants to merge 1 commit into
ahujasid:mainfrom
obselate:fix/distinguish-blender-errors

Conversation

@obselate

@obselate obselate commented Apr 19, 2026

Copy link
Copy Markdown

Summary

When user Python raises inside execute_blender_code, the server currently returns:

Error executing code: Communication error with Blender: Code execution error: <real exception>

The Communication error prefix implies a transport/socket failure, but the socket is healthy — it's a normal Python exception that round-tripped successfully through the addon. First-instinct response is to restart Blender / reconnect the MCP, which wastes triage time. The socket is also dropped unnecessarily by the catch-all, so every user-code error forces a reconnect on the next call.

Fix

  • New BlenderCommandError exception class for errors the addon reported via {"status": "error"} (socket healthy, addon responsive).
  • BlenderConnection.send_command raises BlenderCommandError instead of a generic Exception, and re-raises it through the catch-all without wrapping and without nulling self.sock.
  • execute_blender_code catches BlenderCommandError specifically and returns Blender Python error: <exc> with the addon's duplicate Code execution error: prefix stripped. True transport failures still return Communication error: ....

All other @mcp.tool endpoints already have a generic except Exception as e: catcher and inherit a cleaner error message for free — no changes needed in their bodies.

Before / after

Before (Python NameError in executed code):

Error executing code: Communication error with Blender: Code execution error: name 'foo' is not defined

After:

Blender Python error: name 'foo' is not defined

Before (socket dies mid-call):

Error executing code: Communication error with Blender: [WinError 10054] ...

After:

Communication error: [WinError 10054] ...

Test plan

  • With the patched server installed (uv pip install -e .), call execute_blender_code with code that raises (raise ValueError('x')) → response starts with Blender Python error:.
  • Kill the addon mid-call → response starts with Communication error:.
  • Confirm the socket is NOT nulled for a Python exception: call execute_blender_code with failing code, then immediately call a succeeding command — should reuse the same socket (no reconnect log).
  • Other tools (get_object_info on a missing object, set_texture with a bad slot) return the addon's error message without a Communication error with Blender: prefix.

Filed from downstream tracking as issue Blender-ntr in a workspace accumulating blender-mcp fixes; happy to follow up with the rest of the queue (version exposure, visual-verification tooling, material-slot helpers) if there's interest.

Summary by CodeRabbit

  • Bug Fixes
    • Enhanced error handling and messaging for Blender Python code execution failures
    • Improved error diagnostics with clearer distinction between Blender execution errors and communication failures

Python exceptions inside execute_blender_code surfaced as
'Communication error with Blender: Code execution error: <real exc>',
implying a transport/socket failure when the socket was healthy and
the addon had responded normally with an error status.

Introduce BlenderCommandError for addon-reported errors and let it
propagate through send_command's catch-all without re-wrapping (and
without nulling the socket). execute_blender_code returns these as
'Blender Python error: <exc>' with the addon's duplicate prefix
stripped. True transport failures still return 'Communication error'.

All other tools inherit a cleaner error message as a side-effect
(they already caught Exception generically).
@qodo-code-review

Copy link
Copy Markdown

Review Summary by Qodo

Distinguish Blender addon errors from transport failures

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Introduce BlenderCommandError exception to distinguish addon errors from transport failures
• Addon-reported errors no longer wrapped as communication errors, socket preserved
• execute_blender_code returns cleaner "Blender Python error" message without duplicate prefixes
• Other tools inherit improved error messages through existing generic exception handlers
Diagram
flowchart LR
  A["Addon responds with error status"] --> B["BlenderCommandError raised"]
  B --> C["Re-raised without wrapping"]
  C --> D["Socket preserved for reuse"]
  E["execute_blender_code catches BlenderCommandError"] --> F["Returns 'Blender Python error'"]
  G["True transport failure"] --> H["Caught as generic Exception"]
  H --> I["Returns 'Communication error'"]
Loading

Grey Divider

File Changes

1. src/blender_mcp/server.py 🐞 Bug fix +28/-4

Distinguish addon errors from transport failures

• Added new BlenderCommandError exception class for addon-reported errors
• Modified send_command to raise BlenderCommandError instead of generic Exception when addon
 returns error status, and re-raise it without wrapping to preserve socket
• Updated execute_blender_code to catch BlenderCommandError separately and return "Blender
 Python error" message with addon's duplicate prefix stripped
• Changed generic exception handler in execute_blender_code to return "Communication error" for
 true transport failures

src/blender_mcp/server.py


Grey Divider

Qodo Logo

@coderabbitai

coderabbitai Bot commented Apr 19, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Added a new BlenderCommandError exception type to distinguish Blender addon failures from communication errors. Updated error handling in BlenderConnection.send_command to re-raise this exception unchanged, and modified execute_blender_code to handle the two error types separately with distinct logging levels and user-facing messages.

Changes

Cohort / File(s) Summary
Error Handling & Exceptions
src/blender_mcp/server.py
Introduced BlenderCommandError exception class for Blender addon errors. Updated send_command to re-raise BlenderCommandError without wrapping. Modified execute_blender_code to catch and handle BlenderCommandError separately with info-level logging and user-friendly message formatting, while treating other exceptions as communication failures.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

🐰 Errors now wear their names with pride,
BlenderCommand ones clearly unteide,
While comms mistakes find their own way,
Each handled just right, hip hooray! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: distinguish Blender addon errors from transport failures' directly and clearly describes the main change: separating addon-reported errors from transport/socket failures.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 and usage tips.

@qodo-code-review

qodo-code-review Bot commented Apr 19, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider


Remediation recommended

1. Nested transport error messages 🐞 Bug ≡ Correctness
Description
execute_blender_code prefixes all non-BlenderCommandError exceptions with "Communication error: ",
but send_command already formats many transport failures (e.g., "Connection to Blender lost: ..." or
"Communication error with Blender: ..."), resulting in noisy nested messages and output that may not
match the PR’s intended format.
Code

src/blender_mcp/server.py[R369-371]

    except Exception as e:
-        logger.error(f"Error executing code: {str(e)}")
-        return f"Error executing code: {str(e)}"
+        logger.error(f"Communication error executing code: {str(e)}")
+        return f"Communication error: {str(e)}"
Evidence
execute_blender_code adds a top-level "Communication error:" wrapper for any Exception. send_command
already wraps connection/transport failures with its own prefixes before re-raising, so the final
returned string can include multiple layers of framing (e.g., "Communication error: Connection to
Blender lost: ...").

src/blender_mcp/server.py[163-184]
src/blender_mcp/server.py[345-371]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`execute_blender_code` returns `Communication error: {e}` for all non-`BlenderCommandError` exceptions, but `BlenderConnection.send_command` already raises transport-related exceptions with pre-framed messages (e.g., `Connection to Blender lost: ...`, `Communication error with Blender: ...`). This can create nested/noisy messages and makes it harder to match the intended output format.

### Issue Context
The PR’s goal is clearer error categorization. To keep messaging consistent, either transport errors should be raised as typed exceptions (without embedded prefixes) and formatted at the boundary, or the boundary should avoid re-prefixing already-framed messages.

### Fix Focus Areas
- src/blender_mcp/server.py[163-184]
- src/blender_mcp/server.py[345-371]

### Suggested approach
- Option A (cleanest): introduce a `BlenderTransportError` (or reuse `ConnectionError`) and have `send_command` raise that *without* embedding `Communication error with Blender:` in the message; then `execute_blender_code` formats `Communication error: {raw}`.
- Option B: in `execute_blender_code`, strip known transport prefixes (`Communication error with Blender: `, `Connection to Blender lost: `) before adding `Communication error: `.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Advisory comments

2. Misleading "Python error" label 🐞 Bug ⚙ Maintainability
Description
execute_blender_code treats every BlenderCommandError as a "Blender Python error", but
BlenderCommandError is raised for any addon status:"error" response, including non-user-code
failures like "Unknown command type", which can mislead users about the root cause.
Code

src/blender_mcp/server.py[R359-368]

+    except BlenderCommandError as e:
+        # A Python exception inside the executed code round-tripped cleanly.
+        # The addon prefixes these with "Code execution error: "; strip it so
+        # the user sees the underlying exception without two layers of framing.
+        msg = str(e)
+        prefix = "Code execution error: "
+        if msg.startswith(prefix):
+            msg = msg[len(prefix):]
+        logger.info(f"Blender Python error: {msg}")
+        return f"Blender Python error: {msg}"
Evidence
send_command raises BlenderCommandError for all addon error statuses, regardless of cause. The addon
can emit status:"error" for protocol/command failures (e.g., unknown command), so
execute_blender_code’s fixed "Blender Python error" label is not always semantically correct for
this exception type.

src/blender_mcp/server.py[126-163]
src/blender_mcp/server.py[345-368]
addon.py[255-268]
addon.py[421-436]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`execute_blender_code` currently assumes `BlenderCommandError` always represents a user-code Python exception and returns `Blender Python error: ...`. But `BlenderCommandError` is thrown for any addon `status:error`, including protocol-level errors like `Unknown command type`.

### Issue Context
The addon uses the same `status:error` envelope for multiple kinds of failures. The server-side wording should not be narrower than what the exception actually represents.

### Fix Focus Areas
- src/blender_mcp/server.py[126-163]
- src/blender_mcp/server.py[345-368]
- addon.py[255-268]

### Suggested approach
- In `execute_blender_code`, only label as `Blender Python error:` when the message starts with `Code execution error: ` (the known execute_code exception prefix). Otherwise, return something like `Blender addon error: {msg}` (or `Blender command error: {msg}`) to keep semantics correct even under version/protocol mismatches.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/blender_mcp/server.py`:
- Around line 370-371: Replace the eager f-string logging and explicit str()
conversion with lazy logger formatting and use the !s conversion flag for the
returned string: change the logger call that currently uses
logger.error(f"Communication error executing code: {str(e)}") to use lazy
formatting like logger.error("Communication error executing code: %s", e) and
update the return value from return f"Communication error: {str(e)}" to return
f"Communication error: {e!s}" so the logger defers formatting and the return
uses the conversion flag instead of wrapping str().
🪄 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: 6d5f5e62-ea60-4bfa-b128-39bb1bd9f4ca

📥 Commits

Reviewing files that changed from the base of the PR and between 7636d13 and 082b5b3.

📒 Files selected for processing (1)
  • src/blender_mcp/server.py

Comment thread src/blender_mcp/server.py
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