← Back to the docs
LootX

Compilation and runtime errors

Generated: 2026-10-01 docs.lootx.trade
Справочник

1Compilation and runtime errors

All LS codes that the Editor and chart can show: message text, cause and fix, common errors with examples, runtime limits and cases where you get na instead of an error.

Each LootScript compiler and runtime message starts with a code like LS2008. The code is stable across versions and independent of the UI language, so it’s convenient to search by it. This page lists every code the terminal can show, with the message text, the cause and how to fix it.

Messages appear in Russian when the terminal interface is Russian; for any other language they appear in English. First — the most common errors, then runtime errors and a complete table.

Where errors are visible

At compile time. The Editor compiles the script on each typing pause. Findings appear in the “Problems” tab at the bottom of the Editor: code, text and position in the form “Line 6:6”. Double‑clicking a line moves the cursor to the error location. The Editor header shows the result: “ok · 12 ms”, “warnings: 2” or “errors: 1”.

At runtime. A script that compiles cleanly can still stop on a bar: operation budget exhausted, an index went out of bounds, unknown symbol, etc. Then the “Output” tab will show a line like “Script stopped: LS6004: …”, and the same reason appears in the Strategy Tester. Other scripts, panels and the terminal continue to run.

Diagnostics have three levels:

Level What it means What happens on the chart
Error The script failed to build The script is not added to the chart: “Script with errors is not added to the chart — see ‘Problems’.” If the script was already on charts, the previous working version remains
Warning The script built, but the result may be misleading — for example, it will repaint on the live bar The script runs
Notice The script built, but some setting does nothing The script runs

How codes are organised

Codes Stage About
LS0001–LS0009 Text reading Characters, strings, numbers, colors, the #version directive
LS1000–LS1012 Parsing Brackets, blocks, operator order, script declaration
LS2000–LS2030 Types and names Unknown names, types, arguments, na
LS3000–LS3033 Program semantics ta.* in branches, recursion, strategies, libraries, request.security
LS4000–LS4009 Compilation limits Too many series, outputs, calls
LS5000–LS5013 Repainting and test honesty Values that look different on history than live
LS6000–LS6036 Execution Budgets, indices, collections, strings, drawing objects
LS0999 Internal fault A compiler bug — report it

Common compile errors

LS1009 — missing script declaration

“No script declaration — start with indicator("Name")”. The first statement in the file must be indicator(...), strategy(...) or library(...). The same error appears if the declaration exists but something is written above it. Comments and the #version 1 directive do not interfere.

Loot
// Так нельзя: объявление не первое
len = input.int(14, "Длина")
indicator("RSI")
Loot
indicator("RSI")
len = input.int(14, "Длина")

A second declaration in the same file gives LS1008: a script may have only one.

LS2002 — unknown name

“Unknown name ‘…’ — check spelling or declare it earlier.” Most often a typo or a function without its namespace: indicator functions live in ta, math in math, colors in color.

Loot
avg = sma(close, 20)
Loot
avg = ta.sma(close, 20)

The same error occurs if you read a variable before the line where it’s declared. The full list of names is in the Function reference.

LS2008 — comparison with na

“Comparison with na is always false — use na(x)”. Any comparison with na, including == and !=, yields false, so the compiler rejects such expressions.

Loot
x = ta.sma(close, 50)
plot(x == na ? close : x)
Loot
x = ta.sma(close, 50)
plot(na(x) ? close : x)

The shorter equivalent is plot(x ?? close).

LS2014 — value changes bar-to-bar where a constant is required

“‘…’ in ‘…’ requires a value at least as strong as input, but a series was given — use input.*(…) or a literal.” A window length for ta.* must be known before the first bar. A length chosen by a per-bar condition is not acceptable.

Loot
len = close > open ? 10 : 20
avg = ta.sma(close, len)

Compute both options and choose the result, not the length:

Loot
fast = ta.sma(close, 10)
slow = ta.sma(close, 20)
avg  = close > open ? fast : slow

If the length must be user‑selectable, take it from input.int(...).

LS3004 — ta.* call depends on a variable from a branch

“Argument ‘…’ cannot be computed outside the branch — move the ta.* call to the top level.” ta.* functions remember past bars, so the compiler treats them as computed on every bar even if written inside an if. If the argument is declared only inside the branch, on other bars it simply doesn’t exist.

Loot
var float avgBody = na
if close > open {
    body = close - open
    avgBody := ta.sma(body, 10)
}
Loot
body    = close - open
avgBody = ta.sma(body, 10)

LS2017, LS2007, LS1006 — strings, conditions and chained comparisons

These three errors share a cause: LootScript does not coerce types implicitly.

Code Message How to fix
LS2017 “Cannot add string and number (… + …) — use str.tostring(…)” "RSI " + str.tostring(r) instead of "RSI " + r
LS2007 “Condition must be bool, but here is …” if volume > 0 instead of if volume — numbers are not truthy
LS1006 “Comparisons do not chain — write a < b and b < c” low < close and close < high instead of low < close < high

LS2018 and LS2019 — name already taken

“‘…’ already declared in this scope” (LS2018) — you declared the variable a second time with =. To change a value use :=.

Loot
level = high
level := low

“‘…’ shadows a built‑in name — choose another” (LS2019) — a variable, function or type was named the same as a built‑in series or function: close, time, hour, volume. Rename it: startHour instead of hour. Using namespace names like color or position for variables is allowed.

LS2004 and LS2005 — call arguments

“‘…’ expects … argument(s), but … were given” (LS2004) and “‘…’ has no parameter ‘…’” (LS2005). Check the call against the signature in the Function reference: parameter names must be written exactly as shown.

Loot
plot(close, colour = color.red)
Loot
plot(close, color = color.red)

LS3011 and LS5011 — strategies

“strategy.* is available only in strategy(…)” (LS3011): orders and position state exist only for a script declared with strategy(...). Replace indicator("…") with strategy("…").

“Strategy reads ‘…’: book and tape have no history, a backtest would be fictional” (LS5011): a strategy is tested on history, but book.* and tape.* have no history — they are na on past bars.

Loot
strategy("Book imbalance")
if book.imbalance(10) > 0.5 {
    strategy.entry("L", strategy.long)
}

For historical order book data there’s the depth namespace: where the order book is recorded it gives values on each bar.

Loot
strategy("Book imbalance")
if depth.imbalance(1.0) > 0.5 {
    strategy.entry("L", strategy.long)
}

LS5000–LS5006 — repainting warnings

These warnings do not stop the script. They say the line on history will look different from what was seen live:

  • LS5001 — a value that exists only on the live bar reaches output (barstate.isrealtime, barstate.isnew).
  • LS5000 — a varip value reaches output: it accumulates live‑bar ticks that don’t exist on history.
  • LS5006 — book.* or tape.* reach output: the series is empty on history.
  • LS5003 — higher timeframe value from request.security without [1]: the unclosed bar will repaint.
  • LS5002 — lookahead = true in request.security: the script sees the future on history.
  • LS5005 — math.random or timenow reaches output: two runs give different lines.

If that’s intended — e.g. the indicator is meant only for live trading — the warning can be left.

LS3016 — a setting accepted and does nothing

This is a notice, not an error. It appears in scripts ported from other platforms: the parameter exists for compatibility but has no effect in the terminal. The message’s second part explains why.

What is written Explanation in the message
maxBarsBack in the declaration history is loaded column‑wise in full
format, precision, scale in the declaration the terminal controls scale and its format
timeframe in the declaration the script is calculated on the chart’s timeframe; another timeframe gives request.security
Line width, style or other output setting set by an expression rather than a constant (plot color and mark may change per bar) this build reads the setting only as a constant
color on the fourth and following plot the panel draws only the first three series
location.absolute on plotshape or plotchar the mark has no series to stick to
display that the series doesn’t have that series has no such surface

Runtime errors

A runtime error stops the script on the bar where it occurred. The text appears in the “Output” tab as “Script stopped: LS6004: …”.

LS6004 and LS6005 — script runs too long

“Script exhausted its operation budget on the bar — simplify the loop” (LS6004) and “Script exceeded the time limit for a pass” (LS6005). Each bar has a budget of 2,000,000 operations. Time is limited too: the whole historical pass — 2 seconds, one live‑bar tick — 20 ms. Almost always the cause is a loop that doesn’t terminate or iterates over too much data per bar.

Loot
var int n = 0
i = 0
while i < 10 {
    n := n + 1
}
Loot
var int n = 0
i = 0
while i < 10 {
    n := n + 1
    i := i + 1
}

LS6002 and LS5004 — reading the future

A history index x[n] cannot be negative: close[-1] would mean the next bar. If a negative number is written literally, the compiler rejects it immediately (LS5004). If it comes from a calculation, the script stops with “Negative history offset — cannot read the future” (LS6002). An index larger than the amount of loaded bars is not an error — it yields na.

LS6001, LS6007, LS6019 — collections and objects

  • LS6001 “Index … out of bounds” — array.get, array.set or matrix.get past the size. Check array.size(a) before access.
  • LS6007 “Access to an empty object (na)” — a collection was declared but not created: var array<float> a = na, then a.push(x). Create it with array.new<float>().
  • LS6019 “Drawing object already deleted or evicted by the ceiling — create it anew”. At most 500 objects of one kind live simultaneously; the oldest is evicted. Raise the ceiling via maxLinesCount, maxLabelsCount or maxBoxesCount in the declaration or reuse the object via set_*.

LS6017 and LS6018 — symbol and timeframe in request.security

“Symbol ‘…’ unknown — check the format ‘VENUE:SYMBOL’ or set ignore_invalid_symbol = true” (LS6017) and “Timeframe ‘…’ not parsed — expected ‘5’, ‘60’, ‘4h’, ‘1D’, ‘1W’” (LS6018). With ignore_invalid_symbol = true an unknown symbol yields na instead of stopping.

Execution limits

What is limited Limit Code on exceed
Operations per bar 2,000,000 LS6004
Time for history pass / live tick 2 s / 20 ms LS6005
Array elements 100,000 LS6003
Pairs in dictionary 50,000 LS6003
Matrix elements 1,000,000 LS6003
ta.* window length 100,000 bars LS6034
Line length 100,000 chars LS6014
Table cells 2000 LS6029
Heatmap layers 4 (0…3) LS6036
Drawing objects of one kind 500 by default oldest are evicted
Distinct instrument+timeframe pairs in request.security 8 —
request.security calls 32 LS4009 at compile time

When there’s no error, but there’s no value

Many situations that would crash in other languages give na in LootScript — a gap on the chart, not a stop:

  • arithmetic with na yields na: close - x with empty x is empty;
  • x[n] deeper than the start of history — na;
  • integer division by zero — na; floating division by zero does not stop the script;
  • book.*, tape.* and screener.* on historical bars — na;
  • footprint clusters, delta, open interest and order book history — na on bars where data is absent. Check cluster.available, delta.available and the neighbouring flags;
  • ta.* on the first bars while the window fills — na.

na is never drawn as zero on the chart: the line is interrupted. To substitute a value use nz(x), x ?? fallback or fixnan(x).

All codes

LS0001–LS0009 and LS0999 — text reading

Code Message What to do
LS0001 Unexpected character “…” Remove the character that doesn’t belong to the language
LS0002 String not closed — add a closing quote on the same line Close the quote on the same line
LS0003 Block comment not closed — add */ Close /* … */
LS0004 Unknown escape sequence “…” in string Allowed: \n, \r, \t, \0, \\, \", \' and \u{…}; double a single \
LS0005 Invalid numeric literal “…” Check the number’s notation
LS0006 Number “…” does not fit the type Reduce the number
LS0007 Invalid color literal “…” — expected #RRGGBB or #RRGGBBAA Six or eight hex digits
LS0008 Digit separator “_” at start, end or doubled Write 1_000_000
LS0009 Invalid version directive — expected #version <number> as the first line #version 1 on the first line
LS0999 The compiler failed on this file — this is a build defect, report it Report to support, attach the script

LS1000–LS1012 — parsing

Code Message What to do
LS1000 Unexpected: … Check the line for extra characters
LS1001 Expected “…”, found … Most often a missing closing bracket
LS1002 Expected an expression, found … A value is missing after an operator or comma
LS1004 Expected a name, found … After var, func, . you need a name
LS1005 Expected a block in braces, found … Add { … }
LS1006 Comparisons do not chain — write a < b and b < c Split into two comparisons with and
LS1008 Second script declaration — a script may have only one Leave a single declaration
LS1009 No script declaration — start with indicator(“Name”) First line must be indicator, strategy or library
LS1010 Too deep nesting (> 64) — move part into a function Split the expression or block
LS1012 The body of if / for / while is written in braces: if cond { … } Add braces

LS2000–LS2030 — types and names

Code Message What to do
LS2000 Type mismatch: expected …, got … Pass the value of the required type
LS2001 Cannot convert … to … Convert explicitly: str.tostring, math.round
LS2002 Unknown name “…” — check spelling or declare it earlier Fix the typo, add a namespace (ta.), declare earlier
LS2003 “…” is not a function, cannot call Remove parentheses: it’s a series or a constant
LS2004 “…” expects … argument(s), but … were given Check number of arguments in the reference
LS2005 “…” has no parameter “…” Fix the parameter name
LS2006 Argument “…” passed twice Remove the duplicate
LS2007 Condition must be bool, but here is … Compare explicitly: x > 0, not na(x)
LS2008 Comparison with na is always false — use na(x) na(x) instead of x == na
LS2014 “…” in “…” requires a value at least as strong as …, but got … — use input.*(…) or a literal Literal, input.* or constant instead of a series
LS2015 “…” declared constant — cannot assign; declare with var input.*, loop variables and function parameters cannot be reassigned — copy into your variable
LS2017 Cannot add string and number (… + …) — use str.tostring(…) str.tostring or str.format
LS2018 “…” already declared in this scope Use := to change value or rename
LS2019 “…” shadows a built‑in name — choose another Rename
LS2020 Branches give different types: … and … Make the branches yield the same type
LS2021 switch without default branch “=> …” — add one Add => value
LS2022 “…” element type cannot be inferred — specify it: … array.new<float>()
LS2028 Field “…” of type “…” has no type — write it before the name: float … float price in a type declaration
LS2029 export “…”: an exported function must have all parameter types and a return type Specify types
LS2030 “…” in “…” is read before the first bar — needs a literal or named constant Only constants in the declaration

LS3000–LS3033 — program semantics

Code Message What to do
LS3002 “…” calls itself — recursion is forbidden in LootScript Replace recursion with a loop
LS3003 Mutual recursion forbidden: … Break the cycle
LS3004 Argument “…” cannot be computed outside the branch — move the ta.* call to the top level Compute the argument and call outside if
LS3006 “…” shadows a name from an outer scope (warning) Rename the inner variable
LS3007 “…” outside a loop break and continue only inside loops
LS3008 return outside a function return only in a function body
LS3009 export “…” is allowed only in library(…) Remove export or make the file a library
LS3010 “…” without a single level (profit/loss/stop/limit/trail) — a no‑op (warning) Provide stop, take or trailing
LS3011 strategy.* available only in strategy(…) Declare the script with strategy(...)
LS3012 In a library you cannot draw or declare inputs: … Move outputs and settings into an indicator
LS3013 “…” inside request.security will not become a settings string — declare the input above and pass its value Declare input.* above and pass the variable
LS3016 Setting “…” accepted and does nothing: … (notice) You may leave it or remove it
LS3018 Library “…” not found in the libraries folder — its name is taken from library(“…”, N), not from the filename Check the name in the library declaration
LS3019 Libraries “…” version … not found; installed: … Specify an installed version
LS3020 “…” inside request.security: book and tape have no history on another series Remove book.*, tape.* from the expression
LS3025 Function “…” declared but not called — its body is only tentatively checked (warning) Call the function or delete it
LS3026 “…” requires a stop to size the position: loss/stop on entry or in strategy.exit Add a stop to the entry or strategy.exit
LS3028 This build does not support: … Rewrite without that construct
LS3029 switch branch for “…” repeats — the second is unreachable Remove the duplicate
LS3030 “…” is a chart series, and the request.security expression is evaluated on another series; pass the value via input.* or compute it inside the expression Compute inside the expression
LS3031 Libraries import each other in a cycle: … Break the import cycle
LS3032 In a library “…” only function declarations and imports are allowed — here is … Remove the rest from the library
LS3033 Library “…” does not compile (…) — open it in the Editor and fix it Fix the error in the library itself

LS4000–LS4009 — compilation limits

Code Message What to do
LS4000 Too many series: … at the limit 512 — remove extra ta.* or reuse variables Reduce ta.* calls and history variables
LS4001 Program too large (more than 4096 inlinings) — simplify functions Reduce calls to user functions
LS4002 Too many plots — the panel draws no more than three series Outputs — plot, plotshape, plotchar, bgcolor — no more than 64; the first three plot are drawn
LS4009 Too many request.security calls: …, limit 32 Combine the calls

LS5000–LS5013 — repainting and tester

Code Message What to do
LS5000 varip value reaches output — on history it will differ (warning) Use var if you need identical history
LS5001 Live‑bar‑only value reaches output — it is absent on history (warning) Use barstate.isconfirmed
LS5002 lookahead = true reads the future — unreachable on real time (warning) Remove lookahead = true
LS5003 Higher timeframe without offset — unclosed bar will repaint; add [1] (warning) request.security(…, close[1])
LS5004 Negative offset shifts output into the past — the line knows the future on history Remove negative index x[-n]
LS5005 Non‑deterministic value reaches output — two runs will give different series (warning) Do not output math.random and timenow
LS5006 Data exists only live — the history series is empty (warning) For order book history use depth.*
LS5011 Strategy reads ‘…’: book and tape have no history, a backtest would be fictional Remove book.*, tape.* from the strategy
LS5012 Strategy looks ahead (“…”) — the report is marked as unreachable in real time (warning) Remove lookahead = true
LS5013 “…” enabled: orders execute on bar close, the report is marked (notice) Remove processOrdersOnClose if you need a realistic report

LS6000–LS6036 — execution

Code Message What to do
LS6001 Index … out of bounds Check collection size before access
LS6002 Negative history offset — cannot read the future History index must be ≥ 0
LS6003 Collection size limit exceeded (…) — the collection was created on line … Limit growth: remove old elements
LS6004 Script exhausted its operation budget on the bar — simplify the loop Check loop exit condition
LS6005 Script exceeded the time limit for the pass Reduce work per bar
LS6007 Access to an empty object (na) Create the collection or object before access
LS6014 String longer than the 100000 char ceiling — shorten or build it in parts Shorten the string
LS6015 Unknown timezone “…” — an IANA identifier is required, e.g. “Europe/Berlin” Timezone in IANA format
LS6017 Symbol “…” unknown — check format “VENUE:SYMBOL” or set ignore_invalid_symbol = true Fix the symbol
LS6018 Timeframe “…” not parsed — expected “5”, “60”, “4h”, “1D”, “1W” Fix the timeframe
LS6019 Drawing object already deleted or evicted by the ceiling — create it anew Check the object or raise the ceiling
LS6020 str.format: placeholder {…} has no argument Provide an argument for each {n}
LS6021 str.match: pattern exhausted the step budget — simplify it Simplify the regex
LS6026 Script-wide collection budget exhausted (… cells) — a collection from line … didn’t fit Reduce the number or size of collections
LS6027 Invalid argument “…” in … e.g. negative size in array.new
LS6028 String budget exhausted (…) — reuse strings instead of allocating new ones each bar Do not build new strings each bar
LS6029 Table has more than 2000 cells — this is the panel ceiling Reduce the table
LS6030 Table cell outside the grid: … Column and row numbers must be inside table size
LS6031 Built‑in function “…” declared but not implemented — this is a build defect, report it Report to support
LS6032 Handle does not point to an object of the required kind — the object was freed or the handle is from another run Do not keep references to deleted objects
LS6033 Field … outside type declaration “…” — this is a build defect, report it Report to support
LS6034 Window length … exceeds the 100000 ceiling — such a window won’t fit in memory Reduce the window length
LS6035 Loop step is zero — counter does not move and the end is unreachable by in for cannot be zero
LS6036 Heat layer … outside 0…3 layer from 0 to 3
Codes this version does not issue

These numbers are reserved in the language but not emitted by the current terminal version: LS1003, LS1007, LS1011, LS2016, LS3000, LS3001, LS3005, LS4003, LS4004, LS5007, LS6000, LS6006, LS6008, LS6022, LS6023. For example, “declaration not on the first line” is reported as LS1009 now, and division by zero no longer stops the script with LS6000.

Next

https://docs.lootx.trade/en/loot/errors