Table of Contents

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:

  1. Install .NET 8 SDK on Windows from dotnet.microsoft.com
  2. Verify installation: "/mnt/c/Program Files/dotnet/dotnet.exe" --version
  3. 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.dll
  • handycontrol/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:

  1. Run a clean build: bash build.sh --clean
  2. Verify build output exists in .artifacts/bin/
  3. 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 .rvt models.

Current behavior (by design):

  1. Backup-pattern RVTs under testing/RevitTestModels/ are git-ignored.
  2. 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, and EnsureCleanBuildServers.

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 collectible AssemblyLoadContext (e.g., process-wide AppDomain scans or Assembly.Load(...)), preventing full unload and causing AppLoader's reload to fail with "already loaded".

Required setup:

  1. Point AppLoader to one year folder only:
    • .artifacts/dist/Release/2025 or
    • .artifacts/dist/Release/2026
  2. Build only the running year while Revit is open:
    • bash build.sh -y 2026 BuildAll (or -y 2025)
  3. 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:

  1. Confirm AppLoader is pointing at a single-year folder (for Revit 2024: .artifacts/dist/Release/2024) and the application entry is enabled.
  2. 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.
  3. 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
  4. 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:

  1. Verify DBTools.Themes.dll exists alongside DBTools.dll
  2. Check build output for XAML compilation errors
  3. 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:

  1. Check the resource definition in the XAML file
  2. Ensure all referenced colors/values are static
  3. 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):

  1. DBTools.HandyControl/Themes/SkinDark.xaml
  2. DBTools.HandyControl/Themes/Theme.xaml
  3. DBTools.Themes/Themes/App.Tokens.xaml
  4. DBTools.Themes/Themes/App.Brushes.xaml
  5. DBTools.Themes/Themes/App.Converters.xaml
  6. DBTools.Themes/Themes/App.Controls.Base.xaml
  7. DBTools.Themes/Themes/App.DataGrid.xaml
  8. DBTools.Themes/Themes/App.Menus.xaml
  9. DBTools.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:

  1. Ensure Revit API calls are wrapped in IRevitCallGate.RunAsync()
  2. Check for document availability before operations
  3. 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:

  1. Use WpfUiThread.TryGetDispatcher() and check for null
  2. Check dispatcher.HasShutdownStarted before operations
  3. Use BeginInvoke instead of Invoke for 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:

  1. Programmatically: debugModeService.SetEnabled(true)
  2. On error: Debug mode auto-enables when ISafeExecutor catches an exception
  3. Via Logger Window: Toggle the debug checkbox in the logger window toolbar

Effects of debug mode:

  • Log level changes from Information to Debug
  • 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 to Trace
  • 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-0 insertion.
  • 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:

  1. Log file from %APPDATA%\\DBTools\\Logs\\
  2. Revit version (year and build number)
  3. DBTools version (from add-in manifest)
  4. Correlation ID from the error log
  5. Steps to reproduce the issue
  6. Screenshot of any error dialogs

Log Export

Use the logger window's export feature to save filtered logs:

  1. Open logger window (enable debug mode if needed)
  2. Apply any relevant filters
  3. Click Export button
  4. Save to file with timestamp

Export filename pattern: DBToolsLog_{Timestamp}.txt