Troubleshooting & FAQ

Help

Troubleshooting & FAQ

Problems organised by symptom: a plugin that does not load, an indicator that renders nothing, a strategy without callbacks, a venue that is not listed, missing live data, NaN values and threading errors. Each entry gives the cause, the fix and where to read more.

First, read the Control Center Log tab. Plugin loads, reloads, registration errors and most runtime warnings are written there as they happen, usually naming the DLL or type involved.

Symptom: plugin does not load or appear

The plugin DLL was built but its types do not show up: no indicator in the picker, no strategy in the strategy list, no column in the Market Analyzer.

Cause Fix
The type is not public, is abstract, an interface or an open generic, or has no constructor the platform can call Meet the discovery rules. The most common miss is a constructor with a required parameter.
The DLL is not directly in Documents\SabrTrader\Plugins (a subfolder, the wrong Documents folder, or a file name that matches a built-in plugin assembly) See Where to deploy.
The plugin was built against a newer or different SDK version than the platform ships Rebuild against the matching SDK version. See Versions & targeting.
A rebuilt DLL failed to load, so the previous build is still registered Read the reload error in the log and fix it; the next successful build replaces the previous one.

The full loading checklist is in Building & deploying: Troubleshooting.

Symptom: indicator loads but renders nothing

The indicator appears in the picker and can be added to a chart, but draws nothing.

  • No plot was registered, or no values were written to it. An indicator draws the values in the series behind its plots. Check that the constructor calls AddPlot and that OnDataLoaded and OnBarUpdate write a value for every bar. See Plots & styles.
  • Every value is NaN. A series that is all NaN renders as empty; see NaN values below.
  • The calculation runs at a different cadence than you expect. Check the indicator's Calculate mode and which callbacks you override. See Calculation & market data.
  • Custom rendering throws or draws outside the panel. An exception from OnCustomRender is caught by the chart and logged as OnCustomRender threw, and nothing from that call is drawn. Check the log and your coordinates against PlotArea. See Custom rendering.

Symptom: strategy gets no callbacks

The strategy is selected and started, but your OnBar logic never seems to run.

  • It was not discovered as a strategy. A strategy must be a public, top-level, concrete subclass of Strategy with a public parameterless constructor. See Discovery & metadata.
  • No data series is loaded. Callbacks are driven by incoming bars; without instrument data there is nothing to call back on. Check that the run has a data series.
  • Cadence mismatch. If you expect per-tick calls but the strategy runs per bar (or the other way round), the callbacks fire at a different granularity than you assume. See Calculation cadence.
  • It threw on the first call. An exception in OnInitialize or OnStart stops the strategy before it does visible work; check the log.
  • You rebuilt it while it was running. A running strategy keeps the build it started with. Stop it and start it again to run the new build.

Symptom: venue not listed in Connections

You wrote an IVenuePlugin but its venues do not appear in the Connections dialog.

  • The plugin type failed a discovery rule. The IVenuePlugin implementation must be public, concrete and constructible without arguments. See Discovery rules.
  • Venues is empty. The platform lists one entry per IVenueDescriptor in IVenuePlugin.Venues. Return every descriptor from that property, and give each one a VenueManifest. See Venue plugins.
  • The DLL did not load. Go through the loading checklist above.

Symptom: no live data

A venue is connected but no live ticks, quotes or depth arrive.

  • The symbol or exchange is wrong. A symbol that does not match the venue's listing gives an empty subscription. Check the instrument and exchange.
  • Backfill works but live data does not (or the other way round). History and live ticks are separate parts of a data provider. Check that both are implemented and exposed. See Live ticks & depth and Backfill.
  • Authentication failed for part of the connection. A venue can connect for public market data while a login failure elsewhere is only logged. Check the log for connect and authentication errors.

Symptom: NaN values in a series

A plot or indicator series reads as NaN and renders as a gap or nothing at all.

  • The calculation ran before enough history existed. A 20-period average has no value on bar 3, and NaN is the correct output there. Guard the calculation with a warmup check.
  • A division by zero or a NaN input. One NaN in an arithmetic chain makes the result NaN; validate inputs before using them.
  • NaN is the "no value" marker. A bar written as double.NaN renders as a gap. That is expected.
Use NaN, not 0, for "no value". Writing 0 where you have no value draws a line at zero; writing double.NaN draws a gap. See Reading bars & series.

Symptom: threading exceptions

You see cross-thread exceptions such as "The calling thread cannot access this object because a different thread owns it", or intermittent corrupted state.

Work on the threads the platform gives you. Indicator calculation, strategy callbacks and provider callbacks run on platform-managed threads, and custom rendering runs on the chart's UI thread. Do not create UI objects or touch the platform's UI from plugin code: chart panels and add-on windows are declared from SDK panel elements, whose writes are safe from any thread. Do not mutate state from your own threads that your callbacks or the renderer also read.
  • Share state between data callbacks and rendering safely. Write output through series (one writer, many readers), or publish immutable snapshots that the render callback reads.
  • Avoid blocking calls in a callback. Long or blocking work in a per-tick callback stalls the feed behind it. Start the work elsewhere and pick up the result in a later callback.

Common mistakes

Mistake Consequence Fix
Constructor takes a required parameter Type not discovered, no error line Add a parameterless constructor; expose settings as parameters.
Strategy or drawing tool with only an all-optional constructor Type not discovered Add a public parameterless constructor.
Deploying into a subfolder, or into a Documents folder that is not the real one Builds fine, never appears Deploy directly into Documents\SabrTrader\Plugins. The SDK's DeploySabrTraderPlugin target finds the real Documents folder, a redirected one included.
Copying the whole bin folder Slower loading, log noise Copy your DLL, its PDB and third-party libraries the platform does not ship.
Writing 0 where there is no value A line at zero Write double.NaN for "no value".
Building against a newer SDK than the platform ships Plugin fails to load Build against the SDK version that matches the platform release.

FAQ

Do I need to register my plugin anywhere?

No. There is no registration call or configuration file; the platform discovers your public types by the contracts they implement. Venue plugins and add-ons describe themselves with a manifest object in code. Copy the DLL into the plugin folder and it loads.

Can one DLL contain several plugin kinds?

Yes. One assembly can carry any mix of indicators, strategies, bar types, drawing tools, Market Analyzer columns, venue plugins and add-ons. Each type is cataloged by the contract it implements.

Where does the DLL go?

Directly into Documents\SabrTrader\Plugins. See Where to deploy.

Why does my plugin build but never show up?

Usually one of two reasons: the DLL is not directly in the plugin folder the platform reads, or a discovery rule failed (most often a required constructor parameter). Check the Log tab.

Can I ship third-party libraries?

Yes. Libraries the platform does not ship go next to your plugin DLL and load into your plugin's own context. The SabrTrader.* contract assemblies and any library the platform already ships always come from the platform. See Dependencies & isolation.

Can two plugins use different versions of the same library?

Not from the plugin folder. It is one flat folder, so it holds one copy of each library file name. Each plugin loads that file into its own context, so the plugins do not share statics, but they do share the version.

Do I need to restart SabrTrader after a rebuild?

No. The platform watches the plugin folder and reloads a rebuilt DLL while it runs. Indicators on open charts switch to the new build; a running strategy keeps its build until it stops, and a connected venue switches at its next connect. See The build and reload loop.

What framework should I target?

net10.0, the framework of the SDK assemblies and the platform.

Does a failing plugin crash the platform?

A malformed DLL, a missing dependency or a type that fails to register is logged in the Log tab, and the platform continues. A rebuilt DLL that fails to load leaves the previous build registered.