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:
plotLinethe intermediate series. Seeing the shape of a value over every bar usually tells you immediately whether it is doing what you think.plotTextto print the exact number on the latest bar. When you need the precise value, not just the shape, render it as text.
//@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_BARSmeans no source data reached the bar loop. Nothing iterated, so nothing drew.COMPUTE_ALL_NANmeans a plotted series wasnaon every bar: an indicator that never warmed up, a wrong source member, or an anchor that never reset.RENDER_SPARSE_OUTPUTmeans 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
varinstead of atimeseries, so it kept only the current scalar and lost its shape. Promote it totimeseries. (See Variables for thevarvstimeseriessplit.) - Line starts blank, then appears. The indicator has not warmed up. Anything with a period (a 50-bar EMA, an RSI) is
nauntil it has enough bars. That leading gap is expected; make sure your logic toleratesnabefore 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
nafor no clear reason. A wrong source member. Member names are not checked at compile time, so readingfunding.closewhen the field isfunding.valuesilently yieldsnaon 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.