FAQ

Debugging

A practical workflow for finding out why a kScript script is wrong: plot what you cannot see, read the diagnostics, isolate, and check the usual suspects.

Guide 5 min read

Your script runs but the signal is wrong, or it draws nothing, or a line is mysteriously flat. There is no console.log on a chart, but there is a fast, reliable workflow. Work it in order.

1. Plot what you cannot see

The fastest debugger in kScript is a plot. You cannot step through the bar loop, but you can draw any intermediate value and look at it. When a calculation is suspect, put it on the chart.

Two tools:

  • plotLine the intermediate series. Seeing the shape of a value over every bar usually tells you immediately whether it is doing what you think.
  • plotText to print the exact number on the latest bar. When you need the precise value, not just the shape, render it as text.
scripts/probes/debugging/debug_by_plotting.ks
//@version=2
define(title="Debug By Plotting", position="offchart", axis=true)

timeseries d = ohlcv(symbol=currentSymbol, exchange=currentExchange)

// When a value looks wrong, plot it directly to see what the engine computes.
timeseries spread    = d.high - d.low
timeseries spreadPct = d.close > 0 ? spread / d.close * 100 : 0

plotLine(value=spreadPct, colors=["#ef4444"], width=2, label=["Bar range %"], desc=["high minus low as a percent of close, plotted to inspect it"])

// Print the exact latest value as a label so you can read the number off the chart.
if (isLastBar) {
  plotText(text="".concat("range% = ", math.round(spreadPct[0] * 100) / 100), price=spreadPct[0], color="#f59e0b", size=12)
}

The red line is the intermediate value (bar range as a percent of close) drawn across every bar, so you can watch how it behaves. The text label on the last bar prints the exact current number, rounded for readability. When your real script misbehaves, lift the suspect expression into its own timeseries, plot it like this, and the bug usually becomes visible at a glance: a value pinned at zero, a line that flatlines, a spike where there should be none.

This works for any expression. Wrap the part you doubt in a plotLine, ship it offchart, and read the answer off the chart instead of guessing.

2. Read the runtime diagnostics

If a script compiles and runs but draws nothing, it is usually not a hard error. kScript catches the "ran but blank" cases and surfaces a runtime diagnostic in the editor instead of leaving you with an empty panel. Each has a code that points straight at the cause:

  • COMPUTE_ZERO_BARS means no source data reached the bar loop. Nothing iterated, so nothing drew.
  • COMPUTE_ALL_NAN means a plotted series was na on every bar: an indicator that never warmed up, a wrong source member, or an anchor that never reset.
  • RENDER_SPARSE_OUTPUT means very few finite points relative to the bar count, often a condition that almost never fires.

These codes are the engine telling you exactly where to look. The full table, with every code, its severity, and the matching fix, is in Common Errors. Read the diagnostic first; it frequently saves you the whole hunt.

3. Isolate

When several things are plotted and one is wrong, stop reasoning about all of them at once. Comment out plots until only the suspect series remains, then narrow until the bad value is obvious.

// plotLine(value=fast, ...)
// plotLine(value=slow, ...)
plotLine(value=signal, colors=["#ef4444"], width=2, label=["Signal"], desc=["the one series under investigation"])

Reducing the script to a single output removes every distraction and lets the diagnostics speak about exactly the value you care about. Once that one series is correct, bring the others back one at a time. This is the cheapest way to find which input poisoned a calculation downstream.

4. The usual suspects

Most "wrong script" bugs are one of a handful of patterns. Scan this list against your symptom:

  • Flat or blank line. A series-returning value got held in a var instead of a timeseries, so it kept only the current scalar and lost its shape. Promote it to timeseries. (See Variables for the var vs timeseries split.)
  • Line starts blank, then appears. The indicator has not warmed up. Anything with a period (a 50-bar EMA, an RSI) is na until it has enough bars. That leading gap is expected; make sure your logic tolerates na before the period fills.
  • Flat or blank anchored value. Too little loaded history. An anchored calculation that never crosses its anchor boundary (a monthly anchor inside a window shorter than a month) stays na. Load more bars or pick a shorter anchor.
  • "Zero bars to compute." No source reached the loop. An offchart script with no source has no timeline to walk. Add an ohlcv(symbol=currentSymbol, exchange=currentExchange) anchor so the bar loop has data, even if the indicator does not obviously use price.
  • Everything is na for no clear reason. A wrong source member. Member names are not checked at compile time, so reading funding.close when the field is funding.value silently yields na on every bar. Check the member list for that source type in Data Sources.

Walk these top to bottom. The fix for each is one line, and the diagnostic from step 2 usually tells you which one you are looking at.

See also

  • Common Errors for the full diagnostic table and every hard-error message.
  • Execution Model for why a script needs a source to reach the bar loop.
  • Plotting for plotLine, plotText, and the rest of the output family.