Pine Script v6 diagnostics

Debugging Pine Script: Logs, Values and Reproducible Cases

To debug Pine Script that compiles but produces the wrong result, select one failing bar and compare its inputs, intermediate values, conditions, and saved state with an explicit expected result. Use log.info() for a readable execution trace and plot(..., display = display.data_window) for numeric probes. Record whether the bar is historical, open, or confirmed before changing the logic.

Review a Pine Script Logic Bug

How to debug Pine Script in TradingView

Save a personal copy in Pine Editor and add it to the chart. Open Pine Logs from the editor or script menu after adding log calls. Work on a small bar interval so the relevant messages remain easy to find. This workflow starts after compilation succeeds; a compiler error requires a syntax fix before these observations are available.

  • Record the exchange-qualified symbol, timeframe, chart type, session, inputs, Pine version, and failing bar timestamp with its timezone.
  • State the expected value or condition on that bar and the actual value. A missing marker alone does not identify the failed calculation.
  • Expose every operand of the final condition. For a compound condition, inspect each boolean separately as 1 or 0.
  • Change one cause, rerun the same case, and retain the original observation for comparison. Recheck after reload and on a live open bar when timing matters.
ProbeUseful evidenceConstraint
Pine LogsValues, branch decisions, and local-scope state in execution orderPersonal scripts can generate logs; published scripts cannot. Filter calls in code to avoid excessive output.
Data Window plotsA named numeric value on the bar under the cursorKeep plot calls in global scope. Convert booleans to 1 or 0 explicitly.
Chart markersWhere a condition becomes trueCheck display settings and offsets before concluding that the condition failed.

Case 1: a breakout signal never appears

Suppose the rule is a close above the previous three highs. A comparison against ta.highest(high, 3) includes the current bar. On consistent OHLC bars, close cannot exceed the current high, so that comparison cannot become true. The code below deliberately preserves this logically wrong condition beside its correction: shift the rolling high by one bar, then require the chart bar to be confirmed.

  • The numbers in the table are constructed inputs and hand calculations, not captured chart results. Use the probes to test actual bars.
  • Find the failing Bar index in the Data Window, then set First bar to log and Last bar to log around it. Keep First less than or equal to Last. Bar indices can change when the loaded dataset changes; retain the timestamp too.
  • The ready guard requires the complete previous window. Missing history should remain an explicit unavailable case, not be silently replaced with zero.
  • This rule marks every confirmed close above the previous window. If you want only the first event in a sequence, define and test that separate state rule.
Illustrative input or calculationValueInterpretation
Previous three highs100, 102, 101The intended threshold is 102.
Current high and close104 and 103The current close exceeds the previous threshold.
Window including the current highmax(102, 101, 104) = 104The wrong comparison is 103 > 104: false.
Previous completed windowmax(100, 102, 101) = 102The corrected comparison is 103 > 102: true at confirmation.
Complete v6 diagnostic indicator. wrongBreakout is intentionally logically wrong; confirmedBreakout is the corrected rule.pinescript
//@version=6
indicator("Breakout logic probes", overlay = true)
length = input.int(3, "Previous bars", minval = 1)
firstBar = input.int(0, "First bar to log", minval = 0)
lastBar = input.int(20, "Last bar to log", minval = 0)
logOpenUpdates = input.bool(false, "Also log open-bar updates")

includingCurrent = ta.highest(high, length)
previousHigh = includingCurrent[1]
ready = bar_index >= length and not na(previousHigh)
// Intentional logic bug: the current high is in the threshold.
wrongBreakout = ready and close > includingCurrent
// Correction: compare with the completed window and wait for close.
rawBreakout = ready and close > previousHigh
confirmedBreakout = rawBreakout and barstate.isconfirmed
inLogWindow = bar_index >= firstBar and bar_index <= lastBar

plot(previousHigh, "Previous high", color = color.blue)
plot(bar_index, "Bar index", display = display.data_window)
plot(close, "Close probe", display = display.data_window)
plot(includingCurrent, "Including current high", display = display.data_window)
plot(wrongBreakout ? 1 : 0, "Wrong condition", display = display.data_window)
plot(rawBreakout ? 1 : 0, "Raw condition", display = display.data_window)
plot(confirmedBreakout ? 1 : 0, "Confirmed condition", display = display.data_window)
plotshape(confirmedBreakout, title = "Confirmed breakout", style = shape.triangleup, location = location.belowbar, color = color.blue)
if inLogWindow and (barstate.isconfirmed or logOpenUpdates)
    log.info("bar={0}, time={1}, close={2}, currentWindow={3}, previousWindow={4}, ready={5}, wrong={6}, raw={7}, confirmed={8}, realtime={9}", bar_index, time, close, includingCurrent, previousHigh, ready, wrongBreakout, rawBreakout, barstate.isconfirmed, barstate.isrealtime)

Case 2: a consecutive-bar counter never exceeds one

If the requirement is to count consecutive completed bars whose close exceeds open, a counter initialized to zero on every execution loses its earlier count. Trace the value before and after the update. A persistent var counter retains committed state across bars; updating it only at confirmation makes this example count completed bars. The intentionally broken counter and corrected counter below are both valid syntax.

  • These are expected state transitions derived from the code, not a claimed TradingView execution recording.
  • During an open bar, streak retains the previous completed count. That is deliberate. An intrabar update counter is a different requirement.
  • The count starts at the beginning of the loaded dataset. A streak that began before that boundary cannot be reconstructed without earlier data.
Completed bar from initial count 0Broken countCorrected count
First up bar11
Second consecutive up bar12
A down bar or doji00
Complete v6 indicator: intentional per-execution reset compared with a persistent, confirmed-bar counter.pinescript
//@version=6
indicator("Consecutive-bar state trace")
firstBar = input.int(0, "First bar to log", minval = 0)
lastBar = input.int(20, "Last bar to log", minval = 0)
isUp = close > open
// Intentional logic bug: resets on every execution.
int brokenCount = 0
if barstate.isconfirmed and isUp
    brokenCount += 1

// Correction: persist across bars and update at confirmation.
var int streak = 0
beforeUpdate = streak
if barstate.isconfirmed
    streak := isUp ? streak + 1 : 0

plot(brokenCount, "Broken count", color = color.orange)
plot(streak, "Completed up-bar streak", color = color.blue)
plot(bar_index, "Bar index", display = display.data_window)
if barstate.isconfirmed and bar_index >= firstBar and bar_index <= lastBar
    log.info("bar={0}, time={1}, up={2}, before={3}, after={4}, broken={5}", bar_index, time, isUp, beforeUpdate, streak, brokenCount)

Why history and realtime can disagree

An indicator normally executes once on each historical bar and again as updates arrive on an open realtime bar. An intrabar close can cross a threshold and return before confirmation. In Case 1, enable open-bar logging for the current bar to compare raw with confirmed. Treat a disappearing raw condition as evidence about timing, then decide whether the rule requires an intrabar event or a closing value.

  • An illustrative open-bar sequence is close 103 above a fixed prior threshold 102, followed by close 101 at confirmation. raw can be true earlier while the final confirmed signal is false.
  • Historical bars do not preserve the full realtime tick sequence. Reloading a script cannot reproduce every earlier intrabar observation, including varip-dependent state.
  • Choose the intended timing before applying a repair. Waiting for confirmation changes an intrabar rule; it is not a universal correction for every repainting cause.
ObservationMechanism to inspectRepair or decision
A signal appears and disappears before closeThe current close and other inputs are still changing.For a chart-close rule, gate the final signal with barstate.isconfirmed; accept the later signal.
A var update does not accumulate on each tickRollback restores ordinary persistent state to its last committed value before another open-bar execution.Use var for across-bar state. Use varip only if the specification requires state that survives intrabar rollback.
Logs show an intrabar condition that the final plot does notRealtime log messages survive rollback while the plot is recalculated.Compare timestamp, bar identity, and confirmation state. A log message is not proof of a final signal.
An indicator and strategy produce different tracesStrategies calculate at bar close by default; execution settings can change that schedule.Record calc_on_every_tick and calc_on_order_fills settings before comparing traces.
A requested higher-timeframe value still changesChart-bar confirmation does not confirm a separate requested context.Audit request.security timing and lookahead separately; barstate.isconfirmed is not a general fix inside that request.

Build a reproducible repair request

Provide the smallest script that still reproduces the disagreement and a record of one failing bar plus one control bar. Remove unrelated drawings and conditions incrementally while checking that the same failure remains. Keep the original calculation schedule and requested data contexts; removing them may remove the cause.

IncludeConcrete example of useful evidence
RuleA confirmed close above the highest high of exactly three preceding completed bars.
EnvironmentExact symbol, timeframe, session, chart type, source version, inputs, and strategy execution settings if applicable.
FailureTimestamp with timezone, expected true, actual false, close 103, wrong threshold 104, intended threshold 102. Mark constructed numbers as illustrative.
TraceRelevant log lines and Data Window values, with raw condition, confirmation state, and state before/after.
Acceptance checkThe failing case matches the stated rule; the control case remains unchanged; open-bar and reload behavior are explained.
Where Pineify fits

Pine Script AI Coding Agent

Give Pineify the minimal script, the intended rule, and the failing-bar trace. Ask the agent to explain the mismatch, edit the logic, and check syntax. Compare the returned script with the same cases in TradingView; the agent cannot infer an unprovided tick history or establish behavior from compilation alone.

Review a Pine Script Logic Bug

Frequently asked questions

These examples teach debugging and contain explicitly labeled logic bugs with corrections. Numerical cases are illustrative, not recorded chart executions or trading results. Syntax checks do not validate chart behavior, strategy profitability, or suitability. This is technical education, not investment advice.

Sources and verification

Published by Pineify. Pineify is an independent product and is not affiliated with TradingView. Sources support the technical explanations; examples do not establish trading performance.