Troubleshooting Guide
This guide covers common issues encountered when building, running, and debugging DBTools.
Build Issues
MSBuild Errors
Error: DBT0001 - Build must be run through build.sh
Symptom:
error DBT0001: Raw 'dotnet build' from CLI is not supported. Use bash build.sh instead.
Cause: The build system enforces that all builds go through the repository's build entrypoint to ensure proper configuration, vendored dependency staging, and multi-year target handling.
Solution: Always use the build script:
# Standard incremental build
bash build.sh
# Clean and rebuild
bash build.sh --clean
# Build specific Revit year
bash build.sh -y 2025 BuildAll
# Build only the app
bash build.sh BuildApp
Error: Windows dotnet.exe not found
Symptom:
Windows dotnet.exe not found at: /mnt/c/Program Files/dotnet/dotnet.exe
Cause: The build script runs Windows dotnet.exe from WSL. The .NET SDK must be installed on the Windows host.
Solution:
- Install .NET 8 SDK on Windows from dotnet.microsoft.com
- Verify installation:
"/mnt/c/Program Files/dotnet/dotnet.exe" --version - If installed to a non-default location, set the path in
build.sh
Missing Dependencies
Vendored UI Assemblies Missing
Symptom:
Vendored UI assemblies missing under .artifacts/vendor; building them now...
Or build failures referencing DBTools.HandyControl.
Cause: The vendored UI library (HandyControl) must be built with the DBTools.* namespace before the main build.
Solution:
# Automatic (build.sh runs this if needed)
bash build.sh
# Manual rebuild of vendored deps
bash build-vendored-deps.sh
Expected output location: .artifacts/vendor/
handycontrol/net48/DBTools.HandyControl.dllhandycontrol/net8.0-windows/DBTools.HandyControl.dll
Assembly Load Failures
Symptom:
InvalidOperationException: Failed to load tool assembly 'DBTools.GM'.
Cause: With file-linking architecture, tool assemblies (GM, TDV, SGT, VTC) are compiled into DBTools.dll. This error indicates the main assembly wasn't built correctly.
Solution:
- Run a clean build:
bash build.sh --clean - Verify build output exists in
.artifacts/bin/ - Check that the Revit add-in is loading the correct version
Source: DbtToolAssemblyLoader.cs:10
Revit Test Model Backup Files (*.0001.rvt, *.00001.rvt)
Symptom:
- Backup RVT files appear under
testing/RevitTestModels/after saving test models in Revit.
Cause:
- Revit always writes backup copies when saving
.rvtmodels.
Current behavior (by design):
- Backup-pattern RVTs under
testing/RevitTestModels/are git-ignored. - Build orchestration deletes these backup RVTs during cleanup phases.
Notes:
- You do not need to manually keep these files out of commits.
- Cleanup runs during
PreBuildCleanup,FinalizeRepo, andEnsureCleanBuildServers.
Source: build/Build.cs:216
Source: build/Build.cs:438
Source: build/Build.cs:719
Source: build/Build.cs:748
Source: .gitignore:95
Runtime Issues
AppLoader Hot-Reload Popup: "Assembly already loaded"
Symptom:
- Revit 2025/2026 shows a popup about an already-loaded assembly during or right after
BuildAll. - This is commonly triggered while AppLoader is watching the dist folder and files are being copied.
Likely causes:
- AppLoader is watching a multi-year root (
.artifacts/dist/Release) instead of a single-year folder. - A reload is triggered while the output is being replaced (even with atomic per-file replacement, multiple file updates can still trigger reload attempts).
- Revit 2025+ (net8): DBTools code loaded or resolved a
DBTools.*assembly/type outside AppLoader's collectibleAssemblyLoadContext(e.g., process-wideAppDomainscans orAssembly.Load(...)), preventing full unload and causing AppLoader's reload to fail with "already loaded".
Required setup:
- Point AppLoader to one year folder only:
.artifacts/dist/Release/2025or.artifacts/dist/Release/2026
- Build only the running year while Revit is open:
bash build.sh -y 2026 BuildAll(or-y 2025)
- Use the repository build pipeline so dist promotion uses atomic file replacement semantics.
Notes:
- Revit 2024 (
net48) does not support unload/reload semantics (assemblies cannot be unloaded). DBTools can still be loaded via AppLoader for Revit 2024, but you must restart Revit to pick up a new build. - Revit 2025+ (
net8) is the supported hot-reload path.
Source: build/Build.cs:555-599
Source: build/ArtifactManagement.cs:50-76
Source: build/BuildHelpers.cs:188-295
Source: src/DBTools.Loader/Addin/AddinEntry.cs:17
Source: src/DBTools.Core/Tools/DbtToolAssemblyLoader.cs:39
Source: src/DBTools.Core/Tools/DbtTypeResolver.cs:35
Source: src/DBTools.App/Bootstrap/AppBootstrapper.cs:331
AppLoader (Revit 2024): DBTools doesn't load / no logs
Symptom:
- AppLoader is installed and visible in Revit 2024, but DBTools never shows up (no ribbon buttons) and no DBTools logs are created.
Checklist:
- Confirm AppLoader is pointing at a single-year folder (for Revit 2024:
.artifacts/dist/Release/2024) and the application entry is enabled. - Confirm AppLoader actually executed its load command in that session:
- In the Revit journal, you should see an entry similar to
Execute external command ... CommandAddIn. - If that entry is missing, DBTools will not be loaded in that session.
- In the Revit journal, you should see an entry similar to
- If AppLoader did attempt to load DBTools but it still didn't start, check loader diagnostics (written only on loader exceptions):
%TEMP%\\DBTools.Loader.diag.log%APPDATA%\\DBTools\\Logs\\DBTools.Loader.diag.log
- If Revit 2024 was already running during a rebuild/dist promotion: hot-reload is not supported on net48; restart Revit 2024 to pick up the new build.
- For the dev/AppLoader loop, DBTools.Loader treats AppLoader net48 reload attempts as a no-op after a successful startup to avoid duplicate initialization errors.
Source: src/DBTools.Loader/Addin/AddinEntry.cs:18
Source: src/DBTools.Loader/Addin/AddinEntry.cs:38
Theme Validation Failures
Theme validation runs at startup to catch XAML resource issues early. Failures here indicate broken theme dictionaries or missing resources.
Theme Dictionary Merge Failed
Symptom:
InvalidOperationException: Theme dictionary merge failed at 'pack://application:,,,/DBTools.Themes;component/Themes/App.Brushes.xaml'.
Cause: A XAML resource dictionary failed to load. Common causes:
- Missing assembly reference
- Broken StaticResource chain
- Syntax error in XAML
Solution:
- Verify
DBTools.Themes.dllexists alongsideDBTools.dll - Check build output for XAML compilation errors
- If modifying themes, validate XAML syntax in Visual Studio
Source: DbtThemeValidator.cs:69
Theme Resource Freeze Failed
Symptom:
InvalidOperationException: Theme resource freeze failed for key 'PrimaryBrush' in 'App.Brushes.xaml'.
Cause: A Freezable resource (brush, geometry) could not be frozen. This typically indicates the resource has unresolved bindings or dynamic references.
Solution:
- Check the resource definition in the XAML file
- Ensure all referenced colors/values are static
- Remove any bindings from Freezable resources
Source: DbtThemeValidator.cs:161
Theme Contract Mismatch
Symptom:
InvalidOperationException: Theme merged dictionary contract mismatch: expected 9 dictionaries but found 8 in 'App.Theme.xaml'.
Cause: The theme root dictionary doesn't match the expected structure. This catches accidental removal or reordering of theme dictionaries.
Expected merged dictionaries (in order):
DBTools.HandyControl/Themes/SkinDark.xamlDBTools.HandyControl/Themes/Theme.xamlDBTools.Themes/Themes/App.Tokens.xamlDBTools.Themes/Themes/App.Brushes.xamlDBTools.Themes/Themes/App.Converters.xamlDBTools.Themes/Themes/App.Controls.Base.xamlDBTools.Themes/Themes/App.DataGrid.xamlDBTools.Themes/Themes/App.Menus.xamlDBTools.Themes/Themes/App.Components.xaml
Solution: Ensure App.Theme.xaml contains all dictionaries in the correct order.
Source: DbtThemeValidator.cs:191
Revit API Errors
RevitContextUnavailableException
Symptom:
RevitContextUnavailableException: No UIApplication in current gate scope.
Or:
RevitContextUnavailableException: ActiveUIDocument is required but was not available.
Cause: Code attempted to access Revit API objects outside of a valid Revit context. This happens when:
- A modeless window tries to access Revit without using the call gate
- An async operation continues after the document was closed
- Code runs during Revit shutdown
Solution:
- Ensure Revit API calls are wrapped in
IRevitCallGate.RunAsync() - Check for document availability before operations
- Handle cancellation when documents close
Source: RevitContextUnavailableException.cs:6
WPF Dispatcher Issues
Symptom:
InvalidOperationException: No WPF Dispatcher is available (Application.Current is null and no Revit window dispatcher could be resolved).
Or:
InvalidOperationException: WPF Dispatcher is shutting down.
Cause: WPF UI operations attempted when no dispatcher is available, typically during early startup or late shutdown.
Solution:
- Use
WpfUiThread.TryGetDispatcher()and check for null - Check
dispatcher.HasShutdownStartedbefore operations - Use
BeginInvokeinstead ofInvokefor non-blocking operations
Source: WpfUiThread.cs:21
Tool-Specific Issues
Generic Model Tool (GM)
GmKernelBuildException
| Error Code | Message | Solution |
|---|---|---|
1001 |
Failed to resolve family or type names | Check that all referenced families exist in the project |
1003 |
Shared parameter deserialization failed | Check shared parameter file integrity |
1004 |
Usage data collection failed | Ensure document is fully loaded before scanning |
Source: KernelExceptions.cs:6
GmInvalidMappingException
| Error Code | Message | Solution |
|---|---|---|
2001 |
Operation metadata missing | Ensure mapping configuration is complete |
2002 |
Target type creation failed | Check family loading and type creation permissions |
2003 |
Shared parameter bind failed | Verify parameter definitions exist |
2004 |
Shared parameter embed failed | Check parameter embedding permissions |
2005 |
Replacement operation failed | Validate replacement targets exist |
GmSnapshotLoadException
| Error Code | Message | Solution |
|---|---|---|
4001 |
Snapshot deserialization failed | Re-export snapshot; file may be corrupt |
4002 |
Snapshot checksum mismatch | Re-export snapshot; data integrity issue |
Transfer Drafting Views Tool (TDV)
| Error Code | Message | Solution |
|---|---|---|
DestinationTypeMissing |
Destination view type not found | Create matching view type in destination |
SourceTypeNameUnavailable |
Source view type name not available | Check source view is a valid drafting view |
CreateViewFailed |
Failed to create destination view | Verify write permissions and view limits |
CopyElementsFailed |
Failed to copy view elements | Check element validity and target view |
OverridesFailed |
Failed to copy view overrides | Some overrides may not be transferable |
Source: TdvPerViewErrorCode.cs:3
View Template Comparer (VTC)
VTC Body Template Resource Not Found
Symptom:
System.IO.IOException: Cannot locate resource 'ui/resources/vtcbodytemplates.xaml'.
Cause: VTC body templates are loaded through a pack://application URI, but tool XAML is file-linked into DBTools.dll under Tools/... paths. Using UI/Resources/... fails to resolve the compiled BAML resource.
Solution: Ensure VTC template registration points to:
pack://application:,,,/{assembly};component/Tools/Testing/VTC/UI/Resources/VtcBodyTemplates.xaml
Source: VtcCommandHandler.cs:132
Source: DBTools.App.csproj:69
VTC Process Crash: Read-Only Binding in Process Dialog
Symptom:
System.Windows.Markup.XamlParseException: A TwoWay or OneWayToSource binding cannot work on the read-only property 'SelectionCount' ...
Cause: Process dialog counter Run.Text bindings targeted read-only VM properties (SelectionCount, PendingOverrideCount) without explicit OneWay mode, allowing WPF to attempt an invalid source update path.
Solution: Bind read-only Process counters explicitly with Mode=OneWay.
Source: VtcProcessDialogBodyViewModel.cs:37
Source: VtcBodyTemplates.xaml:354
Debugging
Enabling Debug Mode
Debug mode provides detailed logging and surfaces the logger window on errors.
Methods to enable:
- Programmatically:
debugModeService.SetEnabled(true) - On error: Debug mode auto-enables when
ISafeExecutorcatches an exception - Via Logger Window: Toggle the debug checkbox in the logger window toolbar
Effects of debug mode:
- Log level changes from
InformationtoDebug - Logger window becomes visible
- Hook execution start/completion lines for high-frequency background hooks are suppressed
- Diagnostic output is summarized at
Debug, with deep probe/transaction detail moved toTrace - More detailed stack traces in logs
- Faster log buffer flush (120ms vs 600ms)
Source: src/DBTools.Core/Execution/SafeExecutor.cs:460
Source: src/DBTools.Core/Tools/DbtHookHost.cs:153
Source: src/DBTools.Core/Revit/UI/ContextualRibbonInjectorBase.cs:293
Source: src/Tools/Testing/ERFT/Features/Commands/ErftContextualRibbonInjector.cs:152
Source: src/Tools/Structural/SGT/Features/Placement/TempTransaction.cs:74
Log File Locations
Log files are written to the user's local app data directory:
%LOCALAPPDATA%\DBTools\Logs\
Log file naming pattern:
dbtools-{RevitYear}-{InstanceId}-{Timestamp}-{Nonce}.log
Example: dbtools-2025-ABC123-20260124-143022345-a1b2c3d4.log
When the logger window's Start New Log File action is used, a manual suffix is appended:
dbtools-{RevitYear}-{InstanceId}-{Timestamp}-{Nonce}-manual-{ManualTimestamp}.log
Example: dbtools-2025-ABC123-20260206-123412845-a1b2c3d4-manual-20260206-123412pm.log
Log retention policy:
- Maximum 50 files across all instances
- Maximum 14 days retention
- Maximum 100 MB total size
- Automatic cleanup on startup
Source: LoggingConstants.cs:120, DbtLoggingHost.cs:111, DbtLoggingHost.cs:150
Using the Logger Window
The logger window provides real-time log viewing with filtering capabilities.
Features:
- Level filtering: Toggle INFO, WARN, ERROR, DEBUG visibility
- Search: Filter logs by text content
- Export: Save filtered logs to a file
- Auto-scroll: Automatically scroll to new entries
- Correlation IDs: Track related log entries across operations
- Start New Log File: Danger-menu action that switches file logging to a new file, clears the logger UI, and posts a single confirmation entry while keeping the same instance ID/session context
Source: LoggerWindow.xaml:360, LoggerWindowViewModel.cs:561, DbtLoggingHost.cs:156
Window title format:
DB Tools Log - Revit {Year} [{InstanceId}]
Opening the logger window:
- Automatically opens when debug mode is enabled
- Automatically opens when an unhandled error occurs
- Can be opened via tools menu (if available)
Understanding Correlation IDs
Every operation executed through ISafeExecutor is assigned a correlation ID (GUID). This ID appears in all related log entries:
[Start] GM Apply starting (CorrelationId=abc123...)
... operation logs ...
[Complete] GM Apply completed in 1234ms (CorrelationId=abc123...)
Use the correlation ID to:
- Filter related log entries
- Track operation duration
- Correlate errors with their triggering operations
Common Error Messages
Quick Reference Table
| Error Message | Category | Solution |
|---|---|---|
DBT0001: Raw 'dotnet build' not supported |
Build | Use bash build.sh |
Theme dictionary merge failed |
Theme | Rebuild themes, check XAML syntax |
Theme resource freeze failed |
Theme | Remove bindings from Freezable resources |
Failed to load tool assembly |
Assembly | Clean rebuild: build.sh --clean |
No UIApplication in current gate scope |
Revit API | Wrap calls in IRevitCallGate.RunAsync() |
ActiveUIDocument is required |
Revit API | Check document is open before operations |
WPF Dispatcher is shutting down |
UI | Check dispatcher state before UI operations |
AppRuntime not initialized |
Runtime | Ensure add-in is fully loaded |
Manifest missing required field |
Manifest | Check tool manifest YAML syntax |
Tool module type not found |
Assembly | Verify assembly name in manifest |
Contextual Ribbon Layout Shifts (buttons/panels move)
Symptom:
- A Revit contextual modify tab layout changes unexpectedly while using DBTools (e.g., native actions appear “shifted”).
Cause:
- A contextual ribbon injector can mutate Revit’s contextual tabs even when the current selection does not contain tool-owned elements (for example, injecting into “Multi-Select” tabs eagerly and/or inserting panels/buttons at index
0).
Fix:
- Inject lazily (only when the selection contains matching elements).
- Append panels/buttons (use
Add) rather than forcing index-0insertion. - Remove injected panels when the selection no longer matches.
Source: src/DBTools.Core/Revit/UI/ContextualRibbonInjectorBase.cs:335
Source: src/Tools/Testing/ERFT/Features/Commands/ErftContextualRibbonInjector.cs:194
ISafeExecutor Error Phases
All tool entrypoints run through ISafeExecutor, which logs structured execution phases:
| Phase | Log Level | Meaning |
|---|---|---|
[Start] |
Info | Operation beginning |
[Complete] |
Info | Operation finished successfully |
[Cancel] |
Warning | Operation was cancelled |
[Error] |
Error | Operation failed with exception |
Source: SafeExecutor.cs:12
WPF "Unhandled UI exception" / AppLoader popups
If a WPF window command uses ISafeExecutor.RunAsync(...) and then rethrows into an AsyncRelayCommand, the exception can surface as a WPF Dispatcher unhandled exception (and may be shown by external loaders/hot-reload hosts).
Fix (WPF commands): set SafeExecuteOptions.ThrowOnError = false (and optionally ThrowOnCancel = false) so ISafeExecutor logs + notifies, but does not rethrow into the Dispatcher.
Also watch for XAML binding defaults: WPF Run.Text bindings can default to TwoWay. If a Run.Text="{Binding SomeReadOnlyProperty}" binds to a get-only property, the window can fail to load with a XamlParseException on the Revit UI thread.
Fix (XAML): avoid Run.Text bindings for read-only properties, or explicitly set Mode=OneWay / bind via a TextBlock.Text MultiBinding instead.
Source: src/DBTools.Core/Execution/SafeExecutor.cs:612
Source: src/DBTools.Core/Notifications/Shell/NotificationBannerWindow.xaml:1
Getting Help
Diagnostic Information to Collect
When reporting issues, gather:
- Log file from
%APPDATA%\\DBTools\\Logs\\ - Revit version (year and build number)
- DBTools version (from add-in manifest)
- Correlation ID from the error log
- Steps to reproduce the issue
- Screenshot of any error dialogs
Log Export
Use the logger window's export feature to save filtered logs:
- Open logger window (enable debug mode if needed)
- Apply any relevant filters
- Click Export button
- Save to file with timestamp
Export filename pattern: DBToolsLog_{Timestamp}.txt