Overview#
Writing API code without a debugger means guessing. Fusion supports real debugging of Python scripts and add-ins through Visual Studio Code (VS Code) and the Microsoft Python extension. You can set breakpoints, inspect variables, step line by line, and evaluate expressions in the debug console while the script runs inside Fusion. This page sets up that workflow, shows what to do when the debugger will not attach, and lists the simpler logging techniques that remain useful when a debugger is not practical.
Fusion bundles its own Python. Autodesk's documentation says that when you edit or debug a Python script or add-in, Fusion uses VS Code, and that debugging needs the Microsoft ms-python.python extension, which Fusion installs automatically the first time it opens VS Code. > Note: not confirmed in Autodesk's documentation: how the debugger connects (earlier drafts of this page described debugpy and a local port, launch.json keys and stub-file locations; none of that is in the mirror, so it is now marked as general guidance where it remains).
Where to find it#
- In the Scripts and Add-Ins dialog, select a script or add-in and click Edit in code editor (pencil). Fusion opens the item in VS Code. (In the old dialog the Debug entry in the Run drop-down "does the same thing as Edit".) Then start debugging from VS Code.
- In VS Code, the Python extension (
ms-python.python) is installed for you by Fusion on first use. - The Text Commands window (Autodesk's help lists a Show/Hide Text Commands command; the palette id is
TextCommands) showsapp.logoutput. - TypeScript: you "must first edit the script from Fusion before debugging it", which starts the debug server and updates the VS Code workspace configuration. C++ is debugged with Visual Studio or Xcode (see the C++ page).
Step by step#
1. Install the tooling#
- You do not need to install anything by hand: the first time you choose Edit on a Python script, Fusion offers to install VS Code, and the first time VS Code starts from Fusion it installs the Python extension. When the VS Code install finishes, repeat the Edit step.
- You do not need a system Python for Fusion scripts; the interpreter is Fusion's.
2. Start debugging#
- Open Scripts and Add-Ins, select your script and click Edit in code editor so it opens in VS Code.
- Click the left edge of the code window to add a breakpoint where you want execution to stop.
- Start debugging with Run > Start Debugging or F5. Fusion starts executing your script and stops at the first breakpoint it hits.
- When you have finished, click Disconnect to end the session (Autodesk: "you'll need to click this button to stop debugging"). You can then edit and debug again; a script can be stopped and restarted repeatedly from VS Code.
- While stopped, Fusion's UI is unresponsive because the script runs on Fusion's main thread.
3. Step and inspect#
Use the debug toolbar or shortcuts:
| Action | Shortcut | Effect |
|---|---|---|
| Continue | F5 | Run to next breakpoint |
| Step over | F10 | Run the current line, not entering calls |
| Step into | F11 | Enter the called function (your own code only; API internals are native) |
| Step out | Shift+F11 | Finish the current function |
| Restart | Ctrl+Shift+F5 | Autodesk says restart "doesn't currently work with Fusion Scripts or Add-Ins"; disconnect and start again |
| Disconnect / Stop | Shift+F5 | End the debugging session |
While paused:
- The Variables panel shows locals and globals. Expand
designto see properties such asrootComponent; expand collections to see items. - The Watch panel evaluates expressions you type, like
root.bRepBodies.count. - The Debug Console is a live Python prompt in the paused frame. You can call
app.log('hi'),ui.messageBox('x'), and even create geometry. Be careful: changes you make here affect the open document. - Conditional breakpoints: right-click a red dot > Edit Breakpoint > Expression, such as
body.name == 'Base', to pause only in specific iterations. - Logpoints: right-click the gutter > Add Logpoint to print a message without editing code, such as
{sketch.name} has {sketch.profiles.count} profiles.
Tip: Stepping into a call such as
extrudes.add(ext_input)will not show inner code; Fusion's API is a native layer. Instead inspect inputs before the call and results after.
4. Debug an add-in#
Autodesk's procedure for add-ins:
- While writing the add-in, uncheck Run on Startup, and make sure the add-in is not already running (a running add-in has the wheel icon). If it is, stop it.
- Start debugging from VS Code as for a script. Fusion loads the add-in and calls
run, which typically builds the UI and connects events and then appears to be done; the add-in is still running, waiting for an event. - Switch to Fusion and run the add-in's command. Breakpoints in the command-created handler are now hit.
- To debug
stop, use Stop in the Scripts and Add-Ins dialog; Fusion callsstopand your breakpoints there are hit. - If you disconnect the debugger or are forced to stop, the add-in keeps running in Fusion; stop it from the dialog. If you start debugging it again, Fusion calls its
stopmethod before starting the new session.
General guidance, not Autodesk data: Python caches imported modules, so if you split your code across modules and edits are not picked up, importlib.reload(commands) at the top of run can help during development. Remove it from released code.
Environment, packages, and type hints#
Autocomplete and type hints#
Autodesk's Python topic explains the code-hint problem: the editor knows that Application.get() returns an Application, but properties typed as a base class (activeProduct returns Product; Selection.entity returns Base) only show base-class members. Two fixes: a type hint, which only helps the editor and checks nothing at run time (if the Manufacture workspace is active, des would hold a CAM product and fail later), or cast, which returns None when the type does not match:
des: adsk.fusion.Design = app.activeProduct # editor hint only
design = adsk.fusion.Design.cast(app.activeProduct) # runtime check, None if not a Design
edge = adsk.fusion.BRepEdge.cast(ui.activeSelections[0].entity)
Note: not confirmed in Autodesk's documentation: stub-file names and
python.analysis.extraPathssettings that earlier drafts described. The TypeScript template ships.d.tsdefinitions instead.
Third-party packages#
Autodesk: "The Python provided with Fusion includes only the core modules that come with a standard installation of Python." The recommended approach is not to add modules to sys.path but to keep a local copy of the module inside your script's folder or a subfolder (Autodesk's example is xlrd under a Modules folder) and import it with a relative path:
from .Modules import xlrd
General guidance, not Autodesk data: pure-Python packages are the safe choice, pip install --target from a system Python can fill such a folder, and compiled packages must match Fusion's Python version and platform, which the documentation does not state. The standard library (json, csv, urllib.request, zipfile, sqlite3, threading, pathlib, xml.etree) covers most needs.
Check which interpreter you are running with a one-off script that logs sys.executable and sys.version.
Logging and diagnosis without a debugger#
| Technique | How | Use when |
|---|---|---|
| Text Commands | app.log('...') | Quick checks |
| Message box | ui.messageBox(str) | Blocking, small amounts |
| Traceback display | traceback.format_exc() in except | Always in run |
| File logging | open(path, 'a') | Add-ins, event code, crash analysis |
logging module | A FileHandler writing to a known path | Larger add-ins |
| Fusion log | app.log can write to the Fusion app log file as well as the Text Commands window | Crashes |
| Windows-only debug box | ctypes.windll.user32.MessageBoxW(None, 'text', 'title', 1) | Worker threads, where ui.messageBox can crash Fusion |
Common errors and what they mean#
General guidance, not Autodesk data: the error texts below are typical symptoms, not messages quoted from the documentation. In Python an API failure raises RuntimeError; in C++ you call getLastError.
| Message | Likely cause | Fix |
|---|---|---|
RuntimeError: 3 : invalid argument ... | Wrong type or value passed to an API call | Print the argument types; check units |
RuntimeError: 2 : InternalValidationError : ... | Fusion rejected the operation (invalid profile, failed feature) | Examine the geometry state; try the same step manually |
AttributeError: 'NoneType' object has no attribute ... | A find or cast returned None | Check itemByName, Design.cast results |
NameError for adsk | Missing import | Add import adsk.core, adsk.fusion |
ModuleNotFoundError | A local module name or path wrong | Check sys.path, package structure |
TypeError: ... must be a ... object | Passing a Python list where an ObjectCollection or API object is expected | Build an ObjectCollection |
| Button does nothing | Handler garbage collected | Store handlers in a module list |
| "id already exists" style errors | Add-in not cleaned up on stop | Remove controls and definitions |
| Edit does nothing | VS Code not installed or extension missing | Let Fusion install them, repeat Edit |
Treat the text after any numeric error code as the useful part.
Options reference#
What Autodesk documents about the debug setup:
| Item | Behaviour | Source |
|---|---|---|
| Edit in code editor | Opens the item in VS Code (Python, TypeScript) or its project file (C++) | Creating Scripts and Add-Ins |
ms-python.python extension | Required for Python debugging; installed automatically on first use | Python Specific Issues |
| Start Debugging | Run > Start Debugging or F5 | Python Specific Issues |
| Disconnect | Ends the session; required before debugging again | Python Specific Issues |
| Restart | Does not currently work with Fusion scripts or add-ins | Python Specific Issues |
| Run on Startup | Uncheck while developing an add-in | Python Specific Issues |
| C++ on Windows | Visual Studio: Debug > Attach to Process, "Native code", Fusion360.exe, then run from Scripts and Add-Ins | C++ Specific Issues |
| C++ on Mac | Xcode: Debug > Attach to Process, "Autodesk Fusion" | C++ Specific Issues |
Note: not confirmed in Autodesk's documentation: the contents of a generated
.vscode/launch.json(type, request, port,pathMappings,justMyCode). Open the file in a fresh template if you need it.
Tips and pitfalls#
Tip: Keep a dedicated "scratch" script with the debug setup so you can test small API calls in the Debug Console quickly: set a breakpoint at the end, then explore live.
Tip: Use
Design.cast,Sketch.cast, and similar and check forNoneto produce friendly messages rather than cryptic attribute errors.
Warning: While paused at a breakpoint Fusion is unresponsive. Do not click in Fusion while paused; resume first. If you stop the debug session while the script is mid-operation, the document may be left half-modified. Use undo (Ctrl+Z) and check the timeline.
Warning: Do not leave debug-only code such as
importlib.reloador hardcoded paths in releases you distribute.
Warning: General guidance, not Autodesk data: if debugging fails from a folder with spaces or non-ASCII characters in its path, try the item from a simple path like
C:\dev\MyAddin.
Practice exercise#
- Create a script that loops over
design.rootComponent.sketchesand counts total sketch curves. - Click Edit, start debugging with F5, set a breakpoint inside the loop, add a conditional expression
sk.sketchCurves.count > 5. - When it stops, use the Watch panel to evaluate
sk.nameandsk.profiles.count, then in the Debug Console runapp.log(sk.name). - Add a logpoint reporting
{sk.name}without editing the file.
Expected result: the debugger pauses only on sketches with more than five curves, the Watch values match the browser, and the Text Commands window shows the log line.
Related#
- Scripts and Add-Ins dialog
- Event handlers
- Packaging and distributing add-ins
- C++ API notes