You finally got your custom indicator to compile. You drop it on the chart, ready to feel like a genius—aaaand 💥 Unhandled exception in OnBarUpdate().

If you’ve ever had NinjaTrader slap you with one of those cryptic errors or freeze your backtest halfway through, you’re not alone. The good news? There’s a simple tool built into C# that can help you dodge those crashes and keep your script running smooth: try/catch.

In this post, we’ll break down what try/catch actually does, how to use it in NinjaScript (without overdoing it), and when it’s better to just fix your logic. From rookie mistakes to advanced debugging and performance tricks, this is your no-fluff guide to writing safer, smarter code.

If you’re new here, make sure you check out the earlier posts too:

🤔 What Is try/catch, Really?

At its core, try/catch is a way to tell NinjaTrader: “Hey, something might go wrong here—and if it does, don’t blow up the entire script.”

Here’s the basic structure:

try
{
    // Code that might fail
}
catch (Exception ex)
{
    // Code to run *if* it fails
    Print("Error: " + ex.Message);
}

When the code inside the try block runs, everything’s normal—unless it hits something that throws an exception. If that happens, NinjaTrader jumps straight to the catch block and skips the rest of the try. This keeps your chart alive and lets you gracefully handle the issue.

🧪 Without try/catch, What Happens?

If you don’t handle exceptions, NinjaTrader will stop your strategy or indicator cold. That means:

  • Your chart may stop updating
  • You’ll get a big error in the Log tab or Output window
  • Your strategy will exit or never finish backtesting

Think of try/catch like a circuit breaker—it doesn’t fix the wiring, but it keeps the house from burning down.

🧠 Real-World Analogy

Imagine you’re unlocking a door. Most of the time, the key works. But what if it doesn’t? Without try/catch, your script just panics and throws the key into the void. With try/catch, it calmly says, “Key doesn’t work—let’s try something else.”

🧭 When to Use try/catch in NinjaScript (and When Not To)

Using try/catch the right way can save your indicator from unexpected crashes, but slapping it everywhere is a recipe for confusion, slower performance, and hidden bugs. Let’s talk about when it makes sense—and when it really doesn’t.

✅ Good Use Cases

These are the scenarios where try/catch can actually protect your script and make development smoother:

📉 1. Debugging risky access (like Close[n]) in early bars
Sometimes, you need to test logic that might reference historical bars that don’t exist yet. NinjaTrader’s SampleTryCatch indicator shows how to trap those failures without killing the script.

try
{
    double total = 0;
    for (int i = 1; i <= 10; i++)
        total += Close[i]; // This will break if CurrentBar < 10

    Value[0] = total / 10;
}
catch (Exception e)
{
    Log("Error calculating average: " + e.Message, LogLevel.Warning);
    Print(Time[0] + " " + e.ToString());
}

🛑 Don’t leave this in production. Once you find the issue, replace with a proper guard like:

if (CurrentBar < 10)
    return;

🎨 2. Rendering with SharpDX brushes
When creating custom visuals using SharpDX, each chart render target needs its own resources. Resizing the chart, changing tabs, or hit-testing can all trigger OnRenderTargetChanged(), which is where you should safely (re)create things like brushes.

public override void OnRenderTargetChanged()
{
    try
    {
        if (dxBrush != null)
            dxBrush.Dispose();

        if (RenderTarget != null)
            dxBrush = Brushes.Blue.ToDxBrush(RenderTarget);
    }
    catch (Exception ex)
    {
        Print("Brush creation error: " + ex.Message);
    }
}

This avoids runtime DirectX errors like:

D2DERR_WRONG_RESOURCE_DOMAIN: The resource was realized on the wrong render target.

🔉 3. Optional file or sound input from the user
If you’re letting users set file paths or pick a sound file, they could choose something that doesn’t exist. Wrap those calls so the rest of the script isn’t affected.

try
{
    PlaySound(SoundAlert);
}
catch (Exception ex)
{
    Print("Could not play sound: " + ex.Message);
}

🚫 Bad Use Cases

These are the scenarios where try/catch is more harmful than helpful:

❌ Wrapping all of OnBarUpdate()

try
{
    // Entire logic inside
}
catch { } // Silent failure = disaster

This hides bugs and makes them hard to track down. Worse, it can severely impact performance if you’re doing this on every bar or tick.

❌ Using it instead of proper checks
Most NinjaTrader errors can be avoided with good pre-conditions:

if (CurrentBar < 10) return;
if (BarsInProgress >= BarsArray.Length) return;
if (!BarsArray[1].IsValidDataPoint(0)) return;

Don’t use try/catch to cover laziness—it’s a safety net, not a substitute for clean logic.

🧠 Smarter Error Handling: Filters, Fallbacks, and Debug Tricks

Now that you’ve seen how to use try/catch, let’s make it smarter. We’re going to look at how to catch specific types of errors, give your code a safe fallback, and actually learn from the errors instead of just silencing them.

🎯 Catching Specific Exception Types

You’ve probably seen catch (Exception ex)—but did you know you can catch specific errors too? C# lets you “stack” multiple catch blocks to handle different types of problems in different ways.

Let’s break it down:

try
{
    double val = Convert.ToDouble(UserInput);
}
catch (FormatException ex)
{
    Print("That’s not a valid number format.");
}
catch (OverflowException ex)
{
    Print("The number is too big or too small.");
}
catch (Exception ex)
{
    Print("Something unexpected went wrong: " + ex.Message);
}

💡 What’s happening here?

  • FormatException is thrown when UserInput is something like "abc"—you can’t turn that into a number.
  • OverflowException happens if the number is so big or small it can’t be stored in a double.
  • Exception is the base class for all exceptions. If nothing else matches, this one will catch it.

🧱 Think of it like this:

  • Each catch is a filter.
  • The first one that matches the error gets executed.
  • After one catch runs, the rest are ignored.

👉 You can stack as many catch blocks as you want—but only one will run per error.

⚙️ Why This Is Better Than Just Exception

If you always catch everything like this:

catch (Exception ex)
{
    Print("Error: " + ex.Message);
}

…you’ll never know what kind of error it was. And if you only care about a certain type (like bad user input), you might end up hiding a bug that should be fixed instead.

By catching specific types:

  • You make debugging easier
  • You can respond differently to different problems
  • You avoid covering up real issues

🪛 Safe Fallbacks with Helper Functions

Instead of wrapping every line in a try/catch, sometimes it’s cleaner to push risky logic into a helper method.

Example: Division

public double SafeDivide(double numerator, double denominator)
{
    try
    {
        return numerator / denominator;
    }
    catch (DivideByZeroException)
    {
        return 0; // or double.NaN or whatever fallback makes sense
    }
}

Now in your main code:

double risk = SafeDivide(accountBalance, tradeCount);

🧼 Cleaner. Easier to test. Safer.

📋 Better Logging and Debugging

When something breaks, you want to know:

  • What failed
  • When it happened (time)
  • And ideally, why

Here’s how to get all three:

catch (Exception ex)
{
    if (State >= State.Terminated)
        return;

    Log("Error during processing at " + Time[0], LogLevel.Warning);
    Print("Detailed error info: " + ex.ToString());
}
  • Log() sends a message to the NinjaTrader Control Center > Log tab
  • Print() sends full detail to the Output window
  • Time[0] helps you line it up with what was happening on the chart

🛑 Never Swallow Exceptions Silently

This is a common mistake:

catch { } // ❌ Bad: you caught it, but didn’t do anything with it

You just told NinjaTrader: “If something breaks, I don’t want to know about it.” That’s how bugs sneak into production and ruin trading logic.

Always log or print something. Even just:

catch (Exception ex)
{
    Print("Something went wrong: " + ex.Message);
}

That tiny print can save you hours of head-scratching later.

📚 What Are DivideByZeroException, FormatException, and Exception ex?

When something goes wrong in your code—like dividing by zero or converting a bad string—C# creates an exception object to describe what broke. This object is thrown, and if you have a try/catch, you can grab it and do something with it.

Let’s break it down:

catch (DivideByZeroException ex)
  • DivideByZeroException is the type of error you’re catching.
  • ex is just a variable name that holds the error object.
  • You can use ex.Message, ex.StackTrace, or just Print(ex.ToString()) to see what happened.

🧠 Why So Many Exception Types?

Because not all errors are created equal. Here’s a quick guide to some common exceptions you’ll see in NinjaScript development:

Exception Type When It Happens Example
DivideByZeroException You divide a number by 0 double avg = total / 0;
FormatException You try to convert a string that’s not formatted right Convert.ToDouble("abc")
OverflowException A number is too big or too small for the data type Convert.ToInt32("99999999999")
IndexOutOfRangeException You try to access something outside a list or series Close[50] when CurrentBar is 10
NullReferenceException You use an object that hasn’t been set (it’s null) myBrush.Opacity = 0.5f; when myBrush = null
Exception (generic) Catches any of the above if you didn’t name it Always include this as your final safety net

🧱 Catching Specific vs. Catching Everything

You can have multiple catch blocks, and C# will pick the first one that matches the actual error type. That’s why order matters:

try
{
    // Some risky code
}
catch (FormatException ex)
{
    Print("Formatting error: " + ex.Message);
}
catch (Exception ex)
{
    Print("General error: " + ex.Message);
}

In this case:

  • If a FormatException happens, the first catch runs.
  • If any other error happens, it goes to the second catch.

If you put the generic catch (Exception) first, the specific ones below it are ignored and won’t even compile.

🧭 So… Which Ones Should You Use?

For most NinjaScript work, here’s a practical approach:

  • Start with catch (Exception ex) during early development or debugging.
  • ✅ If you’re working with user input or math, also add:
    • FormatException
    • DivideByZeroException
    • OverflowException
  • ✅ If you use custom rendering or SharpDX objects, add:
    • NullReferenceException
  • ✅ Always end with a final catch (Exception ex) to catch anything you missed.

You don’t need to use all of them every time—but if you know what kind of error you’re expecting, it’s better to catch it directly.

🔁 Reusable try/catch: Make Error Handling Clean and Consistent

If you’ve ever copy-pasted the same try/catch block into multiple spots, you know it starts to clutter your script fast. A better way? Wrap your error handling into a reusable method that you can call anywhere.

💡 The Goal: Keep Your Logic Clean

Instead of this:

try
{
    double result = CalculateRisk();
}
catch (Exception ex)
{
    Print("Error: " + ex.Message);
}

You can write:

SafeExecute(() =>
{
    double result = CalculateRisk();
});

Much cleaner—and easy to reuse.

🛠️ How to Build It

Here’s a simple SafeExecute method you can drop into any indicator or strategy:

public void SafeExecute(Action action)
{
    try
    {
        action();
    }
    catch (Exception ex)
    {
        if (State >= State.Terminated)
            return;

        Print("SafeExecute error: " + ex.Message);
    }
}

This uses C#’s Action delegate to let you pass in any block of code. It’s a great fit for:

  • Isolated calculations
  • Property parsing
  • Drawing logic
  • Rendering segments

✨ Bonus: A Version with Fallback Return Values

What if you want to return a result and catch errors? Here’s a version that gives you a fallback if something breaks:

public T SafeReturn<T>(Func<T> func, T fallback)
{
    try
    {
        return func();
    }
    catch (Exception ex)
    {
        Print("SafeReturn error: " + ex.Message);
        return fallback;
    }
}

Now you can do this:

double risk = SafeReturn(() => CalculateRisk(), 0);

That means if CalculateRisk() fails, you still get a result—and your chart keeps going.

✅ These patterns are especially useful when you’re working with unreliable data, custom rendering, or user-defined inputs. You protect the core logic of your script without burying everything in repetitive try/catch blocks.

🧹 Final Thoughts: Error Handling That Doesn’t Suck

Error handling in NinjaScript isn’t about being perfect—it’s about being prepared. You’re building tools in a live, fast-moving environment, and unexpected things will happen: missing bars, null brushes, divide-by-zero math, bad user input… the works.

🛡️ That’s where try/catch shines—not just as a safety net, but as a debugging ally and code stability booster.

Here’s the short list to keep in mind:

  • ✅ Use try/catch to protect code that might fail—but don’t wrap everything out of fear.
  • ✅ Catch specific exceptions (FormatException, DivideByZeroException) when you know what to expect.
  • ✅ Always log or print the error during development—don’t silently fail.
  • ✅ Use guards (if (CurrentBar < 10) return;) when you can prevent errors up front.
  • ✅ Keep your code clean with helpers like SafeExecute() and SafeReturn().

Remember: the goal isn’t to avoid every error—it’s to write scripts that handle failure gracefully and keep going without breaking your chart or strategy.

Because nothing’s worse than hitting Play on your backtest… and getting slapped with a red log message 2 seconds later.

🎉 Prop Trading Discounts

💥91% off at Bulenox.com with the code MDT91

Categorized in:

Learn NinjaScript,

Tagged in: