Diagnostics
Every code of the language, by code. What causes it, how to fix it, and a wrong and a right version of the code.
When something is wrong, the editor shows the line and a message. Every message has a stable code, which this page is sorted by, and which never changes its meaning. Find your message below: each section starts with the text of the message (the parts that change are written in braces, such as {name}; a part in square brackets is added only when it applies), then gives the cause, the fix, and for most a short script that shows the mistake and one that corrects it. Support and this documentation name a problem by its code.
There are three kinds. An error stops the script from running; its code is E and a number (E3101) or E- and words (E-DT-ZONE). A warning (W-) lets the script run. A hint (H-) comes with an error and suggests what to write.
The errors that come from the engine while a script runs, and the limits of the platform, are on Engine messages.
Characters, text, numbers and times#
The E10xx codes come from reading the text of the script: quotes, brackets, characters and literals. They are reported before anything else, because a script that cannot be read cannot be checked.
E1001#
Message. A text is not closed (it started with {quote})
Cause. A text was opened with a quote and the line ended before the matching quote.
Fix. Close the text with the same quote, or use a triple-quoted text if it must span lines.
indicator "Example"
edition = 1
let name = "Close
plot(close)Corrected:
indicator "Example"
edition = 1
let name = "Close"
plot(close, name = name)E1002#
Message. Tabs are not allowed in indentation: indent with spaces
Cause. A line is indented with a tab character. Indentation is spaces only, because a tab shows as a different width in different editors.
Fix. Replace the tab with spaces (four is the usual). Set your editor to insert spaces for the Tab key.
E1003#
Message. A colour is written #RRGGBB or #RRGGBBAA, not {text}
Cause. A colour starting with # does not have six or eight hexadecimal digits.
Fix. Write #rrggbb, or #rrggbbaa with a transparency pair. A colour name such as color.red works too.
indicator "Example"
edition = 1
plot(close, color = #12345)Corrected:
indicator "Example"
edition = 1
plot(close, color = #123456)E1004#
Message. Unexpected character "{char}": remove it, or write it inside a text
Cause. A character appears that has no meaning in the language, such as $, outside a text.
Fix. Remove it, or put it inside a text. The error often comes with a hint about the form you meant.
indicator "Example"
edition = 1
plot(close $ 2)Corrected:
indicator "Example"
edition = 1
plot(close * 2)E1005#
Message. This line is indented to a width that no block above uses
Cause. A line is indented to a width that none of the blocks above uses. Blocks must go back to a level that exists.
Fix. Indent the line to the width of a block that is open, or to the width of the block you want to leave.
indicator "Example"
edition = 1
if close > open
plot(1)
plot(2)Corrected:
indicator "Example"
edition = 1
if close > open
mut up = 1
plot(close)E1006#
Message. The bracket "{char}" is {what}: every bracket needs its pair
Cause. A bracket has no partner: an opening bracket is never closed, or a closing bracket was never opened.
Fix. Add the missing bracket or remove the extra one. Check the line the message names and the lines just before it.
indicator "Example"
edition = 1
plot(closeCorrected:
indicator "Example"
edition = 1
plot(close)E1007#
Message. This number is not written correctly: {text}
Cause. A number is not written in a form the language reads, such as 1.2.3.
Fix. Write one decimal point at most. Use 1_000 to group digits and 1e3 for an exponent.
indicator "Example"
edition = 1
plot(1.2.3)Corrected:
indicator "Example"
edition = 1
plot(1.2)E1008#
Message. Unknown escape "{seq}" in a text
Cause. A backslash in a text is followed by a letter that is not an escape.
Fix. Use \n, \t, \", \', \\ or \u{...}. To write a backslash itself, write two.
indicator "Example"
edition = 1
plot(close, title = "a\q")Corrected:
indicator "Example"
edition = 1
plot(close, name = "a\nb")E1009#
Message. "{seq}" is not a character: \u{...} needs 1 to 6 hex digits, up to 10FFFF
Cause. A \u{...} escape does not hold one to six hexadecimal digits, or names a code above 10FFFF.
Fix. Write the code of an existing character, for example \u{1F600}.
indicator "Example"
edition = 1
plot(close, title = "Smile \u{110000}")Corrected:
indicator "Example"
edition = 1
plot(close, name = "Smile \u{1F600}")E1010#
Message. A "{char}" in an f-text is not closed or not doubled: write {char}{char} for the character itself
Cause. In a formatted text a { or } is not closed, or is not doubled.
Fix. Close the brace, or double it ({{ or }}) when you want the character itself.
indicator "Example"
edition = 1
plot(close, title = f"{close")Corrected:
indicator "Example"
edition = 1
plot(close, name = f"{close:.2f}")E1011#
Message. The digit "{found}" is not an ASCII digit: write "{expected}"
Cause. A Persian or Arabic digit is written where an ASCII digit is needed.
Fix. Write the digit with 0 to 9. The error carries the replacement as a fix.
indicator "Example"
edition = 1
plot(ta.sma(close, ۲۰))Corrected:
indicator "Example"
edition = 1
plot(tech.sma(close, 20))E1012#
Message. The sign "{found}" is not an ASCII sign: write "{expected}"
Cause. An Arabic comma or semicolon is written where an ASCII one is needed.
Fix. Replace it with , or ;. The error carries the replacement as a fix.
indicator "Example"
edition = 1
plot(math.max(1،2))Corrected:
indicator "Example"
edition = 1
plot(math.max(1, 2))E1013#
Message. The quote "{found}" is not an ASCII quote: write {expected}
Cause. A curly quote, as word processors write, is used to open or close a text.
Fix. Use the straight quote " or '.
indicator "Example"
edition = 1
plot(close, title = “Close”)Corrected:
indicator "Example"
edition = 1
plot(close, name = "Close")E1014#
Message. The sign "{found}" is not the one the language uses: write "{expected}"
Cause. A sign that looks like an operator (a multiplication sign, a long dash) is used.
Fix. Write the ASCII operator: *, /, -, <=, >= or !=.
indicator "Example"
edition = 1
plot(close × 2)Corrected:
indicator "Example"
edition = 1
plot(close * 2)E1020#
Message. This is not a valid clock time: {text}
Cause. A time of day is not a valid hour and minute, such as 25:99.
Fix. Write hours 00 to 23 and minutes 00 to 59: 08:30.
indicator "Example"
edition = 1
plot(25:99)Corrected:
indicator "Example"
edition = 1
plot(08:30)E1021#
Message. This is not a valid date or time: {text}
Cause. A date or an instant is not a real date and time, such as month 13.
Fix. Check the year, month, day, hour and minute: @2026-09-17T07:10Z.
indicator "Example"
edition = 1
plot(@2026-13-45T00:00Z)Corrected:
indicator "Example"
edition = 1
plot(@2026-09-17T07:10Z)E1022#
Message. This is not a time zone the chart knows: "{name}"
Cause. A time zone name is not one the chart knows.
Fix. Use a name from the time zone database, such as "Europe/London" or "America/New_York", or "UTC".
indicator "Example"
edition = 1
session london = 08:00 .. 16:00 @ "Mars/Olympus"
plot(if london.active then 1 else 0)Corrected:
indicator "Example"
edition = 1
session london = 08:00 .. 16:00 @ "Europe/London"
plot(if london.active then 1 else 0)E1023#
Message. A duration is written with one unit (90m, not 1h30m): {text}
Cause. A duration has two units, such as 1h30m.
Fix. Write one unit: 90m.
indicator "Example"
edition = 1
plot(1h30m)Corrected:
indicator "Example"
edition = 1
plot(90m)E1090#
Message. The script is too large: {limit} characters is the most
Cause. The script is longer than the number of characters one script may have.
Fix. Make the script shorter: remove what you do not use. The number is on Limits and budgets: 400,000 characters.
E1091#
Message. The script has too many tokens: {limit} is the most
Cause. The script has more tokens (words, numbers and signs) than the limit.
Fix. Split it, as for E1090. The limit is 250,000 tokens.
E1092#
Message. A line is too long: {limit} characters is the most
Cause. A single line is longer than the limit.
Fix. Break the line: after a comma, an operator or inside brackets. The limit is 20,000 characters.
E1093#
Message. This is nested too deep ({what}): {limit} levels is the most
Cause. Brackets or blocks are nested deeper than the limit.
Fix. Give an inner part a name with let, or move it to a function. The limits are 64 brackets and 40 blocks.
Layout and statements#
The E2xxx codes come from the shape of the statements: blocks, headers, inputs, match and imports.
E2001#
Message. An if used as a value needs an else
Cause. An if ... then ... used as a value has no else.
Fix. Add the else branch. A value must exist whichever way the condition falls.
indicator "Example"
edition = 1
let tint = if close > open then color.green
plot(close)Corrected:
indicator "Example"
edition = 1
let tint = if close > open then color.green else color.red
plot(close, color = tint)E2002#
Message. Expected {what}, found {found}
Cause. The parser expected one thing (a name, a comma, a closing bracket) and found another.
Fix. Read the message: it says what was expected. Look at the end of the line before the one named.
indicator "Example"
edition = 1
let = 5
plot(1)Corrected:
indicator "Example"
edition = 1
let five = 5
plot(five)E2003#
Message. A block must be indented under its first line
Cause. A line that starts a block (if, for, fn …) is followed by a line that is not indented deeper.
Fix. Indent the lines of the block one level under its first line.
indicator "Example"
edition = 1
if close > open
plot(1)Corrected:
indicator "Example"
edition = 1
if close > open
mut up = 1
plot(close)E2004#
Message. A block needs at least one line
Cause. An indented block holds no line that can be read as one of its own kind, for example a group whose lines are not inputs or an enum whose body is not made of names. (A block that is empty, or whose first line is not indented, is E2003.)
Fix. Put at least one valid line in it, or remove the line that starts it.
E2005#
Message. Unexpected {found}: a statement ends at the end of its line (end a line with an operator or a comma to go on)
Cause. A statement is followed by more on the same line, or by something that cannot go on. A statement ends where its line ends.
Fix. Put each statement on its own line. To continue a statement, end the line with an operator or a comma, or leave a bracket open.
indicator "Example"
edition = 1
let a = 1; let b = 2
plot(a + b)Corrected:
indicator "Example"
edition = 1
let a = 1
let b = 2
plot(a + b)E2006#
Message. Expected a value, found {found}
Cause. A value was expected and something else was found, for example a closing bracket after a comma.
Fix. Write the value, or remove the comma.
indicator "Example"
edition = 1
plot(close, title = )Corrected:
indicator "Example"
edition = 1
plot(close, name = "Close")E2010#
Message. Comparisons do not chain: write (a < b) and (b < c)
Cause. Comparisons are written in a chain, such as a < b < c.
Fix. Write two comparisons joined by and: a < b and b < c.
indicator "Example"
edition = 1
plot(if 1 < close < 5 then 1 else 0)Corrected:
indicator "Example"
edition = 1
plot(if 1 < close and close < 5 then 1 else 0)E2011#
Message. "=" gives a name a value; to compare write "=="
Cause. A single = is used where a comparison is meant.
Fix. Write == to compare. A single = gives a name a value.
indicator "Example"
edition = 1
if close = open
mut up = 1
plot(close)Corrected:
indicator "Example"
edition = 1
if close == open
mut up = 1
plot(close)E2021#
Message. Unknown number format "{spec}"
Cause. A formatted text has a number format the language does not know.
Fix. Use a format such as .2f, ,.2f, +.1f, .1%, 03 or price. Text and number formatting lists them.
indicator "Example"
edition = 1
plot(close, title = f"{close:10.2f}")Corrected:
indicator "Example"
edition = 1
plot(close, name = f"{close:.2f}")E2030#
Message. The input "{name}" needs a type or a literal default: input {name}: int = 5
Cause. An input has neither a type nor a default to read one from.
Fix. Write the type, the default, or both: input length: int = 20.
indicator "Example"
edition = 1
input length
plot(length)Corrected:
indicator "Example"
edition = 1
input length: int = 20
plot(length)E2031#
Message. The option "{name}" is repeated, or a positional value follows a named one
Cause. An option of an input is given twice, or a value without a name comes after a named one.
Fix. Give each option once, and put the title (the value without a name) first.
indicator "Example"
edition = 1
input a: int = 1, title = "A", title = "B"
plot(a)Corrected:
indicator "Example"
edition = 1
input a: int = 1, name = "A"
plot(a)E2032#
Message. This input has two tooltips: a /// line above it and one at the end of its line
Cause. An input has two tooltips: a /// line above it and a second /// at the end of its own line.
Fix. Keep one of them.
indicator "Example"
edition = 1
/// How many bars
input length: int = 20 /// Another text
plot(length)Corrected:
indicator "Example"
edition = 1
/// How many bars
input length: int = 20
plot(length)E2041#
Message. A loop step of 0 never moves
Cause. A loop step written as 0 would never move.
Fix. Use a step that is not zero. To count down, use a negative step such as by -1.
indicator "Example"
edition = 1
mut count = 0
for i in 0 to 5 by 0
count += 1
plot(count)Corrected:
indicator "Example"
edition = 1
mut count = 0
for i in 0 to 5 by 1
count += 1
plot(count)E2050#
Message. A match arm needs "=>" after its pattern, found {found}
Cause. A line in a match has a pattern but no => and result.
Fix. Write pattern => result on each line.
indicator "Example"
edition = 1
let n = match close
1
plot(n)Corrected:
indicator "Example"
edition = 1
let n = match int(close) % 2
0 => 1
_ => 2
plot(n)E2051#
Message. "_" must be the last arm of a match, and only once
Cause. The default case _ of a match is not the last line, or is written twice.
Fix. Move _ to the end, and write it once.
indicator "Example"
edition = 1
let n = match int(close) % 2
_ => 0
1 => 1
plot(n)Corrected:
indicator "Example"
edition = 1
let n = match int(close) % 2
1 => 1
_ => 0
plot(n)E2052#
Message. Write two arms instead of "a | b"
Cause. Two patterns are joined with | on one line.
Fix. Write one line for each pattern.
indicator "Example"
edition = 1
let n = match int(close) % 3
1 | 2 => 1
_ => 0
plot(n)Corrected:
indicator "Example"
edition = 1
let n = match int(close) % 3
1 => 1
2 => 1
_ => 0
plot(n)E2070#
Message. An import needs a version and an alias: import Owner/Name@1 as alias
Cause. An import has no version or no alias.
Fix. Write import Owner/Name@1 as alias.
indicator "Example"
edition = 1
import Me/Stats as mu
plot(close)E2072#
Message. An input must be at the top level of the file or inside a group, not inside a block (an if, a loop or a function)
Cause. An input is written inside a function, an if or a loop.
Fix. Move it to the top level of the file, or inside a group.
indicator "Example"
edition = 1
fn f()
input a: int = 1
plot(close)Corrected:
indicator "Example"
edition = 1
input a: int = 1
plot(a)E2073#
Message. A group lists only inputs
Cause. A group block holds something other than inputs.
Fix. Put only inputs in a group; move other lines out of it.
E2074#
Message. A session is declared at the top level of the file
Cause. A session declaration is not at the top level of the file.
Fix. Move it out of the if, loop or function, to a line of its own.
indicator "Example"
edition = 1
if close > open
session a = 08:00 .. 16:00 @ "UTC"
plot(close)Corrected:
indicator "Example"
edition = 1
session a = 08:00 .. 16:00 @ "UTC"
plot(if a.active then 1 else 0)E2080#
Message. The file must start with indicator "name", strategy "name" or module name
Cause. The file does not start with a header.
Fix. Start with indicator "Name", strategy "Name" or module name, each followed by its indented option lines. The call form, indicator(...), is still read while scripts move to the indented form.
plot(close)Corrected:
indicator "Example"
edition = 1
plot(close)E2081#
Message. The header {kind}(...) is written once
Cause. The header is written twice.
Fix. Keep one header, on the first line of code.
indicator "Example"
edition = 1
indicator("Again", edition = 1)
plot(close)Corrected:
indicator "Example"
edition = 1
plot(close)E2082#
Message. The option "{name}" is given twice in the header or in a block
Cause. An option of the header, or of a block such as setup:, is given twice.
Fix. Give each option once.
indicator("Example", overlay = true, overlay = false, edition = 1)
plot(close)Corrected:
indicator "Example"
edition = 1
display = price
plot(close)E2090#
Message. This expression is nested too deep: {limit} levels is the most
Cause. An expression is nested deeper than the limit.
Fix. Give inner parts a name with let. The limit is 100 levels.
E2099#
Message. Too many errors: stopping here (the limit is {limit})
Cause. The text has so many syntax errors that the parser stopped reporting after the limit. Errors of the checker are cut at the same number without a message.
Fix. Fix the first errors; the rest often come from them. The checker lists at most 50.
E2100#
Message. The header is not written the way this build reads it: write {use} and A call-style header cannot be combined with E1 configuration blocks. Convert the header to the indented form. Mechanical fix: {fix}
Cause. A header is written in two forms: the call form, strategy("Name", ...), and the indented form, strategy "Name" followed by indented name = value lines. The call form is read during the move to the indented form, and the optional blocks setup:, execution: and margin: belong to the indented form only. This code comes in two cases: the front end is set to read one form and the file is written in the other, or a call-style header is followed by one of the blocks.
Fix. Write the header in the indented form: the name after the keyword, then one line for each option, indented. The message gives the line to write.
strategy("Example", edition = 1)
setup:
capital = 10000
plot(close)Corrected:
strategy "Example"
edition = 1
setup:
capital = 10000
plot(close)E2102#
Message. The block "{block}:" is written twice: a strategy has each of setup:, execution: and margin: once
Cause. A block of the header (setup:, execution: or margin:) appears twice in one strategy.
Fix. Put the lines of both in one block.
strategy "Example"
edition = 1
setup:
capital = 10000
setup:
fees = fee.rate(0.05)
plot(close)Corrected:
strategy "Example"
edition = 1
setup:
capital = 10000
fees = fee.rate(0.05)
plot(close)Names, functions, inputs and calls#
The E3xxx codes come from the checker, which reads a well-formed script and looks at names, calls, options, sessions and states before anything runs.
E3101#
Message. "{name}" is already declared in this function (line {line}); pick another name, or give it a new value with =
Cause. A name is declared twice in the same place.
Fix. Choose another name, or give the first one a new value with = (it must be mut or state).
indicator "Example"
edition = 1
let level_ = 10
let level_ = 20
plot(level_)Corrected:
indicator "Example"
edition = 1
let level_ = 10
let upper = 20
plot(level_ + upper)E3102#
Message. "{name}" is not declared: declare it with let, mut or state before giving it a value
Cause. A name is given a value but was never declared.
Fix. Declare it first with let, mut or state.
indicator "Example"
edition = 1
total = 5
plot(total)Corrected:
indicator "Example"
edition = 1
mut total = 5
plot(total)E3103#
Message. "{name}" is {kind}: declare it with mut (a value that restarts every bar) or state (a value that stays between bars) to give it a new value
Cause. A let name, an input or a parameter is given a new value. These never change.
Fix. Declare the name with mut (it starts again on every bar) or state (it is kept between bars).
indicator "Example"
edition = 1
let total = 0
total += 1
plot(total)Corrected:
indicator "Example"
edition = 1
state total = 0
total += 1
plot(total)E3104#
Message. The function "{fn}" gives a value to "{name}", which is declared outside it: pass a record, or return the value
Cause. A function gives a new value to a mut or state name declared outside it.
Fix. Pass the value in as an argument and return the new value, or keep the values in a record.
indicator "Example"
edition = 1
state hits: int = 0
fn count_up(): int
hits += 1
return hits
plot(count_up())Corrected:
indicator "Example"
edition = 1
state hits: int = 0
fn next_count(n: int): int = n + 1
hits = next_count(hits)
plot(hits)E3110#
Message. "{type}" cannot be the type of an input[. Did you mean "{guess}"?]
Cause. The type written after an input name is not one of the input types.
Fix. Use int, float, bool, text, color, source, timeframe, symbol, session, time, price or the name of an enum. The message suggests the nearest.
indicator "Example"
edition = 1
input length: integer = 20
plot(length)Corrected:
indicator "Example"
edition = 1
input length: int = 20
plot(length)E3120#
Message. The id "{id}" is already used (line {line})
Cause. Two inputs, plots or conditions have the same id.
Fix. Rename one, or give it id = "other". Ids explains ids.
indicator "Example"
edition = 1
input length: int = 20
input length: int = 30
plot(length)Corrected:
indicator "Example"
edition = 1
input length: int = 20
input other: int = 30
plot(length + other)E3121#
Message. key and was take a text written in the script, like key = "length"
Cause. key or was is given something other than a text written in the script.
Fix. Write a text: key = "length".
indicator "Example"
edition = 1
let n = "x"
input a: int = 1, key = n
plot(a)Corrected:
indicator "Example"
edition = 1
input a: int = 1, key = "a"
plot(a)E3130#
Message. "{opt}" is not an option of {fn}; options: {list}
Cause. An option name is not one that call takes. The message lists those it does.
Fix. Fix the spelling or remove the option. An unknown option is never ignored.
indicator "Example"
edition = 1
input length: int = 20, minimum = 1
plot(length)Corrected:
indicator "Example"
edition = 1
input length: int = 20, min = 1
plot(length)E3131#
Message. The value of "{opt}" does not fit: write {type}
Cause. The value of an option is of the wrong kind or form for it.
Fix. Read the message: it says what to write, for example a text written in the script or a whole number from 1 to 64.
indicator "Example"
edition = 1
plot(prior(year).high)Corrected:
indicator "Example"
edition = 1
plot(prior(day).high)E3132#
Message. A strategy cannot use future = true: it would trade on prices it could not have seen. Remove it (the default is the last closed bar)
Cause. A strategy uses future = true in a request, so it would trade on prices it could not have seen.
Fix. Remove it. The default reads the last closed bar of the other timeframe.
strategy "Example"
edition = 1
display = price
let day_high = data.series("1D", high, symbol = symbol.id, future = true)
plot(day_high)Corrected:
strategy "Example"
edition = 1
display = price
let day_high = data.series("1D", high, symbol = symbol.id)
plot(day_high)E3133#
Message. {opt} can use only inputs and constants: "{name}" is not one
Cause. The rule of a show_if or a check names something that is not an input or a constant: a price, a series, a let, a call that keeps a state, a list or x[n]. The rule is worked out from the settings alone, not from bars.
Fix. Write the rule with inputs and constants only. If the rule needs a price or a variable, do that part in the script.
indicator "Example"
edition = 1
input depth: int = 3, "Depth", show_if = close > 0
plot(depth)Corrected:
indicator "Example"
edition = 1
input advanced: bool = false, "Advanced"
input depth: int = 3, "Depth", show_if = advanced
plot(depth)E3134#
Message. The show_if of "{name}" depends on itself: through the inputs it names it leads back to "{name}"
Cause. The show_if of an input names inputs whose own show_if lead back to it, so no input could be the first to be decided.
Fix. Make one of the inputs show without a rule, or name another input.
indicator "Example"
edition = 1
input a: int = 1, "A", show_if = b > 0
input b: int = 1, "B", show_if = a > 0
plot(a + b)Corrected:
indicator "Example"
edition = 1
input a: int = 1, "A"
input b: int = 1, "B", show_if = a > 0
plot(a + b)E3135#
Message. The setting "{opt}" can use only inputs and constants of the chart: "{name}" is not one
Cause. A line of setup:, execution: or margin: is worked out once, before the first bar, so it can use only what is known then: inputs, constants of the chart (such as the symbol's tick size) and plain operators and calls on them. A series (close), a state or a call that remembers something between bars is not known before the run.
Fix. Write a number, an input, or an expression made of those. To make a setting adjustable, declare an input and use its name.
strategy "Example"
edition = 1
setup:
capital = close
plot(close)Corrected:
strategy "Example"
edition = 1
setup:
capital = money
input money: float = 10000, "Capital"
plot(close)E3136#
Message. The block "{block}:" belongs at the top level of a strategy: this is not a strategy, or the block is inside another block
Cause. setup:, execution: and margin: configure a strategy's account and fills. They are not read in an indicator or a module, and one block cannot be written inside another.
Fix. Use the block in a strategy, unindented at the start of a line; remove it from an indicator or a module.
indicator "Example"
edition = 1
setup:
capital = 10000
plot(close)Corrected:
indicator "Example"
edition = 1
plot(close)E3140#
Message. return is only valid inside a function
Cause. return is written outside a function.
Fix. Use return only inside an fn.
indicator "Example"
edition = 1
return 5
plot(close)Corrected:
indicator "Example"
edition = 1
fn five(): float
return 5
plot(five())E3141#
Message. This function returns {n} values but its type says {m}
Cause. A function returns a different number of values than its type says.
Fix. Make the tuple match the type: (float, float) means two values.
indicator "Example"
edition = 1
fn pair(): (float, float) = (1.0, 2.0, 3.0)
plot(close)Corrected:
indicator "Example"
edition = 1
fn pair(): (float, float) = (1.0, 2.0)
plot(close)E3142#
Message. break and continue are only valid inside a loop
Cause. break or continue is used outside a loop.
Fix. Use them only inside for or while.
indicator "Example"
edition = 1
break
plot(close)Corrected:
indicator "Example"
edition = 1
mut found = 0
for i in 1 to 10
if i > 3
found = i
break
plot(found)E3143#
Message. A tuple of {n} values is given to {m} names
Cause. A tuple of one size is taken apart into a different number of names.
Fix. Use as many names as the function returns values; _ for one you do not need.
indicator "Example"
edition = 1
fn pair(): (float, float) = (1.0, 2.0)
let (a, b, c) = pair()
plot(a)Corrected:
indicator "Example"
edition = 1
fn pair(): (float, float) = (1.0, 2.0)
let (a, b) = pair()
plot(a + b)E3144#
Message. return, break and continue cannot leave a block that gives a value
Cause. return, break or continue is used inside a block that gives a value, such as an if ... then expression with blocks.
Fix. Compute the value without leaving: put return after the expression, not inside it.
indicator "Example"
edition = 1
fn f(x: float): float
return if x > 0
return 1
else
2
plot(f(close))Corrected:
indicator "Example"
edition = 1
fn f(x: float): float
return if x > 0 then 1 else 2
plot(f(close))E3150#
Message. Two functions "{name}" take the same arguments (line {line})
Cause. Two functions have the same name and take the same arguments.
Fix. Rename one, or give them different arguments.
indicator "Example"
edition = 1
fn f(x: float): float = x
fn f(y: float): float = y
plot(f(close))Corrected:
indicator "Example"
edition = 1
fn f(x: float): float = x
fn g(y: float): float = y
plot(f(close) + g(open))E3151#
Message. "{name}" is defined later (line {line}): define a function before using it
Cause. A function is called before the line where it is defined.
Fix. Move the definition above its first use.
indicator "Example"
edition = 1
plot(f(close))
fn f(x: float): float = xCorrected:
indicator "Example"
edition = 1
fn f(x: float): float = x
plot(f(close))E3160#
Message. "{name}" is not a function this chart knows[. Did you mean "{guess}"?]
Cause. A name that is called is not a function the chart knows.
Fix. Check the spelling and the group: it is tech.sma, not sma. The message suggests the nearest name. The Function index lists them all.
indicator "Example"
edition = 1
plot(sma(close, 5))Corrected:
indicator "Example"
edition = 1
plot(tech.sma(close, 5))E3161#
Message. {fn} takes at most {max} arguments
Cause. A function is called with more arguments than it takes.
Fix. Remove the extra argument.
indicator "Example"
edition = 1
plot(math.abs(1, 2))Corrected:
indicator "Example"
edition = 1
plot(math.abs(-1))E3162#
Message. {fn} has no argument "{name}"; arguments: {list}
Cause. A named argument does not exist for that function. The message lists those that do.
Fix. Fix the spelling of the name.
indicator "Example"
edition = 1
plot(tech.sma(close, lenght = 5))Corrected:
indicator "Example"
edition = 1
plot(tech.sma(close, length = 5))E3163#
Message. {fn} needs {min} arguments ({names}), got {got}
Cause. A function is called with fewer arguments than it needs. The message names the missing ones.
Fix. Add the missing arguments.
indicator "Example"
edition = 1
plot(tech.sma(close))Corrected:
indicator "Example"
edition = 1
plot(tech.sma(close, 20))E3164#
Message. The argument "{name}" of {fn} is given twice
Cause. The same argument is given twice, once by place and once by name.
Fix. Give it once.
indicator "Example"
edition = 1
plot(tech.sma(close, 5, length = 6))Corrected:
indicator "Example"
edition = 1
plot(tech.sma(close, length = 6))E3170#
Message. Two methods "{name}" could take this value: name the type of the value
Cause. Two methods of one name could take the value, and the engine cannot tell which you mean.
Fix. Name the type of the value, or give the methods different names.
E3171#
Message. "{name}" is not declared[. Did you mean "{guess}"?]
Cause. A name is used that was never declared. The message suggests the nearest name.
Fix. Declare the name above its use, or fix the spelling.
indicator "Example"
edition = 1
plot(clos)Corrected:
indicator "Example"
edition = 1
plot(close)E3172#
Message. "{name}" is not exported by "{module}"
Cause. A name is read from an imported module, and the module does not export it.
Fix. Mark it export in the module, or use a name the module exports.
E3173#
Message. "{name}[…]" reads the history of "{name}", not an item of the array: write {name}.at(index)
Cause. An array is read with [ ], which reads the history of a series, not an item.
Fix. Use .at(index): levels.at(1).
indicator "Example"
edition = 1
let levels = [close, open, high]
plot(levels[1])Corrected:
indicator "Example"
edition = 1
let levels = [close, open, high]
plot(levels.at(1))E3180#
Message. {name}(...) and the other size and fee helpers belong in the strategy(...) header
Cause. A size or fee helper such as strategy.lots(...) is used in the body of a script.
Fix. These belong in the strategy(...) header: size = strategy.lots(0.1).
indicator "Example"
edition = 1
let s = strategy.lots(1)
plot(close)Corrected:
strategy "Example"
edition = 1
display = price
setup:
size = sizing.lots(1)
plot(close)E3190#
Message. Edition {n} is not supported (this build: {max})
Cause. The header asks for an edition this build does not run.
Fix. Use edition = 1, or leave it out.
indicator "Example"
edition = 2
plot(close)Corrected:
indicator "Example"
edition = 1
plot(close)E3200#
Message. uses takes texts written in the script: write uses "XAUUSD"
Cause. uses is followed by something other than a text written in the script.
Fix. Write uses "XAUUSD".
E3201#
Message. The element type of [] is not known: write let a: array<float> = []
Cause. An empty array [] is written with no way to know what it holds.
Fix. Give it a type: let items: array<float> = [].
indicator "Example"
edition = 1
let items = []
plot(close)Corrected:
indicator "Example"
edition = 1
let items: array<float> = []
plot(close)E3202#
Message. An array written out has at most {max} items
Cause. An array written out has more items than the limit.
Fix. Build it in a loop or read it from data instead of writing it out.
E3210#
Message. {what} needs {min} argument(s) ({list}); this call gives {given}: {names} is (are) missing
Cause. A built-in function was called with fewer arguments than it needs, in a form the checker could not see.
Fix. Add the missing arguments; the message names them.
E3211#
Message. alert.send(once = …) is "bar", "bar_close", "per_day", "on_change" or "all"; "{str}" is none of them
Cause. The once value of alert() is not one the chart knows.
Fix. Use "bar", "bar_close", "per_day", "on_change" or "all".
indicator "Example"
edition = 1
if close > open
alert.send("up", key = "up", once = "sometimes")
plot(close)Corrected:
indicator "Example"
edition = 1
if close > open
alert.send("up", key = "up", once = "bar_close")
plot(close)E3251#
Message. A session that starts and ends at {time} has no hours: give it two different times (one that ends first runs over midnight)
Cause. A session starts and ends at the same time, so it has no hours.
Fix. Give it two different times. If it ends earlier than it starts, it runs over midnight.
indicator "Example"
edition = 1
session a = 08:00 .. 08:00 @ "UTC"
plot(if a.active then 1 else 0)Corrected:
indicator "Example"
edition = 1
session a = 08:00 .. 16:00 @ "UTC"
plot(if a.active then 1 else 0)E3260#
Message. "{name}" is a session: read a member of it, like {name}.active, .start, .end, .index, .high or .low
Cause. A session name is used by itself.
Fix. Read one of its members: .active, .start, .end, .index, .high or .low.
indicator "Example"
edition = 1
session a = 08:00 .. 16:00 @ "UTC"
plot(a)Corrected:
indicator "Example"
edition = 1
session a = 08:00 .. 16:00 @ "UTC"
plot(if a.active then 1 else 0)E3261#
Message. {fn}(...) needs a field: write {fn}(day).high (open, high, low, close, volume or time)
Cause. prior(...) or current(...) has no field after it.
Fix. Name the field: prior(day).high. The fields are open, high, low, close, volume and time.
indicator "Example"
edition = 1
plot(prior(day))Corrected:
indicator "Example"
edition = 1
plot(prior(day).high)E3270#
Message. "{word}" is a unit word of a setting of execution(...) in the strategy header; units as values come with edition 2
Cause. A unit word such as ticks or ms is used outside the execution(...) settings of a strategy header.
Fix. Write a plain number, or use the unit only in the header. Units as values come in a later edition.
indicator "Example"
edition = 1
plot(25 ticks)Corrected:
indicator "Example"
edition = 1
plot(25 * symbol.tick)E3271#
Message. A time with its zone, like 16:45 @ "Europe/London", is the argument of clock.reached
Cause. clock.reached is given a time without its zone.
Fix. Write both as one argument: clock.reached(16:45 @ "America/New_York").
indicator "Example"
edition = 1
plot(if clock.reached(16:45) then 1 else 0)Corrected:
indicator "Example"
edition = 1
plot(if clock.reached(16:45 @ "America/New_York") then 1 else 0)E3280#
Message. The script declares {n} sessions: write the one to start again with, state session NAME x = …
Cause. state session has no session name, and the script declares more than one.
Fix. Name the session: state session london high_so_far = high.
indicator "Example"
edition = 1
session london = 08:00 .. 16:30 @ "Europe/London"
session newyork = 09:30 .. 16:00 @ "America/New_York"
state session top = high
plot(top)Corrected:
indicator "Example"
edition = 1
session london = 08:00 .. 16:30 @ "Europe/London"
session newyork = 09:30 .. 16:00 @ "America/New_York"
state session london top = high
plot(top)E3281#
Message. state session needs a session: declare one, session NAME = 08:00 .. 16:30 @ "Europe/London"
Cause. state session is used in a script that declares no session.
Fix. Declare a session first: session london = 08:00 .. 16:30 @ "Europe/London".
indicator "Example"
edition = 1
state session top = high
plot(top)Corrected:
indicator "Example"
edition = 1
session london = 08:00 .. 16:30 @ "Europe/London"
state session top = high
plot(top)E3301#
Message. {name} keeps its own state for every call site, so inside a loop all passes would share one state. Call it once before the loop (or write each call out)
Cause. A function that keeps state between bars (tech.*, data.series, a function of yours that holds a state) is called inside a loop. Every pass would share one memory.
Fix. Call it once before the loop, or write the calls out one by one.
indicator "Example"
edition = 1
mut total = 0.0
for i in 1 to 3
total += tech.sma(close, 5)
plot(total)Corrected:
indicator "Example"
edition = 1
let average = tech.sma(close, 5)
mut total = 0.0
for i in 1 to 3
total += average
plot(total)E3302#
Message. {call} keeps a state for this place in the script, and here it stands {?in the right side of and{and}?}{?in the right side of or{or}?}{?in the right side of ??{coalesce}?}{?in an arm of if … then … else{arm}?}, which runs only when it is needed, so the state would move on some bars only. To run it on every bar, write it first on a line of its own (let x = …) and use x here; to run it only where it is reached, write the condition as a block if
Cause. A call that keeps a state for the line it is written on (a tech.* call, data.series, math.random, the history of an expression, a function of yours that holds a state) stands directly in the right side of and, or or ??, or in an arm of if ... then ... else. That part runs only when it is needed, so the state of the call would move on some bars only, which the line does not say.
Fix. To run the call on every bar, write it first on a line of its own and use the name. To run it only where it is reached, write the condition as a block if (the warning W3302 then says so).
indicator "Example"
edition = 1
let trend = close > tech.sma(close, 50)
let signal = trend and tech.crosses_above(close, tech.sma(close, 10))
plot(if signal then 1 else 0)Corrected:
indicator "Example"
edition = 1
let trend = close > tech.sma(close, 50)
let crossed = tech.crosses_above(close, tech.sma(close, 10))
let signal = trend and crossed
plot(if signal then 1 else 0)E3310#
Message. "{name}" calls itself ({cycle}): write a loop, or keep the running value in a state
Cause. A function calls itself, directly or through other functions or methods. The message shows the chain, a -> b -> a. The script is refused before it runs, because the depth of such a chain would be decided by the machine that runs the script. The checker cannot always follow a method that has the name of a built-in method; the count of nested calls (E-LIMIT-DEPTH) stops those while the script runs.
Fix. Write a loop, or keep the running value in a state. See Functions.
indicator "Example"
edition = 1
fn total(n: int): int = if n < 1 then 0 else n + total(n - 1)
plot(total(5))Corrected:
indicator "Example"
edition = 1
fn total(n: int): int
mut sum = 0
for i in 1 to n
sum += i
return sum
plot(total(5))E3400#
Message. "{name}" is {found}, but here a {expected} is wanted. "{name}" is also an option word of {expected}: your variable hides it, so rename the variable
Cause. A name you declared is also an option word of the place it is written in (small is a size of mark.shape), and the two do not have the same type. Your name wins, so the argument gets your value, not the word, and the engine says so instead of choosing for you.
Fix. Rename your variable, or write the word where you want the word.
indicator "Example"
edition = 1
let small = 10
mark.shape(close > open, size = small)Corrected:
indicator "Example"
edition = 1
let gap = 10
plot(gap)
mark.shape(close > open, size = small)E3406#
Message. "{name}" is an option word of several sets ({sets}) and nothing here says which: write its type, like let x: v_align = {name}
Cause. A word such as top, left or none belongs to more than one set of option words, and the place it is written in does not say which. This is a name on its own (let s = top), not an argument: an argument has its set from the argument.
Fix. Write the type of the name: let s: v_align = top.
indicator "Example"
edition = 1
let s = top
plot(close)Corrected:
indicator "Example"
edition = 1
let s: v_align = top
plot(close)E3407#
Message. "{name}" is not a word of {type}{?. Did you mean "{guess}"??}. The words: {list}
Cause. A bare word is written where an option word is wanted, and that place does not have the word. The message names the nearest word and lists the words the place has.
Fix. Write one of the words in the list.
indicator "Example"
edition = 1
plot(close, style = lin)Corrected:
indicator "Example"
edition = 1
plot(close, style = line)Requests and reserved forms#
The E4001 error is raised when a script runs and asks for data the chart does not have. The E9xxx codes are forms reserved for later: E9001 for a later phase of edition 1, E9002 for edition 2.
E4001#
Message. {fn}: "{asked}" has no data here — this chart reads only its own symbol ({ticker}). Use symbol.id[ (it is declared in uses, but this host reads only the chart's own symbol for now)]
Cause. A request names a symbol other than the chart's, and there is no data for it.
Fix. Read the chart's own symbol with symbol.id. Other symbols are not available in this release.
indicator "Example"
edition = 1
uses "EURUSD"
plot(data.series("60", close, symbol = "EURUSD"))Corrected:
indicator "Example"
edition = 1
plot(data.series("60", close, symbol = symbol.id))E9001#
Message. "{feature}" is reserved for a later phase ({task}): edition 1 does not run it yet
Cause. A form is reserved for a later phase of the language. It is refused now so that it cannot run with a different meaning.
Fix. Remove it. The message says which feature it is. Limits and budgets lists them.
indicator "Example"
edition = 1
plot(account.equity)Corrected:
indicator "Example"
edition = 1
plot(close)E9002#
Message. "{feature}" is reserved for edition 2
Cause. A form belongs to edition 2 of the language.
Fix. Remove it, or write it in the way edition 1 offers (for example separate orders.enter and orders.exit calls instead of bracket).
strategy "Example"
edition = 1
display = price
bracket "B" long
plot(close)Corrected:
strategy "Example"
edition = 1
display = price
if bar.index == 10
orders.enter("Long", side.long)
plot(close)Errors with a name#
These codes are spelled with words. They are raised when a script runs, or by the checker for a rule that has no number. Some are limits of the platform; those are in Engine messages.
E-CHUNK-LATE#
Message. the {part} part of the engine was asked for after the run had started: {reason}. The run was stopped, and nothing was computed with another build
Cause. The engine loads and checks every part a script needs before its first bar; a part is never taken in the middle of a bar, because the numbers of one run must all come from one build. This message means that something asked for a part after the bars had started to run. A script cannot cause this; it is a defect of the engine, reported instead of going on with a part nobody had checked.
Fix. Nothing in the script needs to change. Run it again. If it comes again, tell support the code. For an alert, the alert is not evaluated and not sent, and the platform's team is told.
E-CHUNK-SKEW#
Message. the {part} part belongs to another build of the engine: {what} is {got}, this page pins {want}. The script was not run
Cause. The engine is published as a set of files that belong together. The site was updated while this page was open, so the files the page asks for now belong to another build than the page itself, or the parts already loaded belong to another build than the one just asked for. The engine never mixes builds: a run is made with one build from start to end, and a newer deployment in the middle of your session does not change a run that is going. A script cannot cause this.
Fix. Nothing in the script needs to change. Reload the page, so that the page and the engine come from the same build. For an alert, the alert is not evaluated and not sent while the build is not the one the platform pinned, and the platform's team is told.
E-DT-ZONE#
Message. A date-time needs a time zone: add Z, +03:30 or [Asia/Tehran]
Cause. A date and time is written with @ and no time zone. The same text would be a different moment on every machine.
Fix. Add Z for UTC, an offset such as +03:30, or a zone in brackets: @2026-09-17 07:10[Asia/Tehran].
indicator "Example"
edition = 1
let start = @2026-09-17 07:10
plot(close)Corrected:
indicator "Example"
edition = 1
let start = @2026-09-17 07:10[Asia/Tehran]
plot(close)E-ENGINE-PART-UNAVAILABLE#
Message. the {part} part of the engine could not be loaded: {reason}. The script was not run
Cause. The engine is not downloaded when a page opens: it is a few parts that are loaded when a script needs them. The script engine itself is the first of them (the first script of a visit loads it); the strategy runner is the second (a strategy needs it, an indicator does not); the deterministic mathematics is the third (math.log, math.log10, math.exp, math.pow, math.sin, math.cos, math.tan, math.asin, math.acos, math.atan and the built-ins that use them). The script needed a part and it could not be had: the file was not there, could not be read, or did not start. A script cannot cause this; it is a fault of the deployment or of the connection. The page tries once more by itself, after a short wait; if that fails too, the message stays and a button offers to try again. The engine never goes on with the browser's own versions of these functions, because they give a slightly different last digit in different browsers: a script that needs a part runs on it or does not run at all.
Fix. Nothing in the script needs to change. Check the connection and press the button to try again, or reload the chart and run again. If it comes again, tell support the code. For an alert, the alert is not evaluated and not sent while the part is missing, and the platform's team is told; the alert is not marked as broken and starts again by itself when the part is back.
E-ENGINE-PART-VERSION#
Message. the {part} part does not match this engine: its {what} is {got}, the engine pins {want}. The script was not run
Cause. The part was found, but it is not the one this engine was published with: its interface version, its version, its fingerprint (the SHA-256 of its bytes) or its answers to a short self-test differ from what the engine expects. That happens when the engine and the part were not published together, or when a copy of the part is damaged. The engine does not run on a part it cannot vouch for. A script cannot cause this.
Fix. Nothing in the script needs to change. Reload the page, so that the engine and the part come together. If it stays, tell support the code. For an alert, the alert is not evaluated and not sent while the part does not match, and the platform's team is told.
E-FMT-SPEC#
Message. text.fmt does not know the format "{sp}" (use .2f ,.2f +.1f .1% 03 price time:HH:mm)
Cause. text.fmt was given a number format it does not know.
Fix. Use one of .2f, ,.2f, +.1f, .1%, 03, price or time:HH:mm.
indicator "Example"
edition = 1
let s = text.fmt(1.5, "q")
plot(close)Corrected:
indicator "Example"
edition = 1
let s = text.fmt(1.5, ".2f")
plot(close)E-FUTURE-READ#
Message. This read of another timeframe looks ahead (future = true) on a value that is not shifted: on the bars of a day it shows the day's final figure, which the bar did not have[, and a strategy would trade on it][, and an alert would ring on it]
Cause. A strategy reads the future of another timeframe: a look-ahead on a value that is not shifted, so it would trade on prices the bar did not have. The checker stops this earlier, with E3132, so you meet this code only if a script gets past it. An indicator, including one that makes alerts, gets the warning W-FUTURE-READ instead.
Fix. Remove future = true: a strategy may not use it, even on a value shifted back.
E-INPUT-RANGE#
Message. Input '{id}' is {value}; maximum is {max}., Input '{id}' is {value}; minimum is {min}., Input '{id}' is {value}; it must be {expected}. and Input '{id}' is {value}; it must be one of: {options}.
Cause. The value an input was given (in the settings, in a saved alert or in a backtest) is outside what the script declares for it: above its max, below its min, not a number (or not a whole number for an int), or not one of its options. The platform does not change the value for you, so a value that is too large never turns into the largest one by itself. The script does not start, and the message names the input, the value and the limit. The line is the line of the input.
Fix. Give the input a value inside the range it declares. If the script is yours and larger values are fine, raise the max of the input; a max also lets the platform keep only as much history as the input can reach (see W-ENGINE-HISTORY-OPEN).
E-LOOP-STEP#
Message. The step of this loop is zero or na: the loop would never reach its end. Give it a step that is not zero
Cause. The step of a loop is zero or na when the loop runs. A step written as 0 is E2041 before it runs.
Fix. Make sure the step can never be zero or na; guard it before the loop.
indicator "Example"
edition = 1
input step: int = 0, name = "Step"
mut n = 0
for i in 0 to 5 by step
n += 1
plot(n)Corrected:
indicator "Example"
edition = 1
input step: int = 1, name = "Step", min = 1
mut n = 0
for i in 0 to 5 by step
n += 1
plot(n)E-MODULE-HASH#
Message. The module "{key}" does not match its hash: its text was changed
Cause. The text of a module is not the text its hash was taken of, so it was changed on the way.
Fix. The text of a module is not the text its fingerprint (a hash) was taken of. You cannot reach this in the editor in this release; if you see it, tell support.
E-MODULE-NOT-FOUND#
Message. One of these:
"{path}" is not the name of a module (Owner/Name/1)The module "{id}" is not found[ (imported by {by})]"{name}@{version}" is not a module name
Cause. A module that a script imports, or that a bundle holds, cannot be found.
Fix. Check the name and version in the import. In this release only your own modules can be imported, and the editor cannot yet save one so that it is found by name (see Modules and libraries).
E-ORDER-ID#
Message. {call}: no entry or order used this id yet — did you mean "{used}"?
Cause. An order id differs from one already used only in letters-case, spaces, underscores or dashes. It is almost certainly a typing mistake, and it would not have closed the trade you meant.
Fix. Use the exact id. The message names the id you used before.
strategy "Example"
edition = 1
display = price
if bar.index == 10
orders.enter("Long", side.long)
if bar.index == 20
orders.close("long")
plot(close)Corrected:
strategy "Example"
edition = 1
display = price
if bar.index == 10
orders.enter("Long", side.long)
if bar.index == 20
orders.close("Long")
plot(close)E-PERIOD-NAME#
Message. One of these:
{fn}: "{period}" is not a period (day, week or month){fn}: "{field}" is not a field ({fields})prior: n is a whole number from 1 to {keep} (the engine keeps the last {keep} periods)prior: n is a whole number from 1 to {keep}, not {got}
Cause. prior() or current() was given a period or field that does not exist, or a count out of range. The checker normally catches this first, with E3131.
Fix. Use day, week or month, a field from open, high, low, close, volume, time, and a count from 1 to 64.
E-PERIOD-TF#
Message. prior({period}) / current({period}) need a chart of bars shorter than a {period}; this chart is {chartPeriod}
Cause. prior(day) or current(day) is used on a chart whose bar is as long as the period or longer, for example prior(day) on a daily chart.
Fix. Use a longer period: prior(week) or prior(month) on a daily chart.
E-QTY-NA#
Message. strategy.{name}: qty is na (the order has no size). Give a number, or leave qty out to use the default size
Cause. The size of an order is na. The order would otherwise silently trade the default size.
Fix. Give a number, or leave qty out to use the default size.
strategy "Example"
edition = 1
display = price
if close > open
orders.enter("Long", side.long, qty = na)
plot(close)Corrected:
strategy "Example"
edition = 1
display = price
if close > open
orders.enter("Long", side.long)
plot(close)E-REGEX-FEATURE#
Message. text.match does not read {feature}
Cause. The pattern given to text.match uses a part that the pattern reader of the chart does not have. {feature} names it: back-references (\1), look-ahead ((?=…) and (?!…)), look-behind ((?<=…) and (?<!…)), named groups, \p{…} properties, or control escapes (\cX). The reader is smaller than the ones in other programs on purpose: it reads the text once, from left to right, so no pattern can keep a script busy for ever. The error comes when the call is evaluated.
Fix. Write the pattern with what the reader has, or split the work into two calls. Text functions lists what it reads. A pattern that is only malformed (an open bracket, for example) is not an error: the call gives an empty text.
indicator "Example"
edition = 1
let twice = text.match("abcabc", "(abc)\\1")
plot(text.length(twice))Corrected:
indicator "Example"
edition = 1
let twice = text.match("abcabc", "(abc){2}")
plot(text.length(twice))E-REGEX-HOST#
Message. text.match is not available in this host: patterns are read where scripts run (the chart worker, the tester, the alert evaluator)
Cause. The place that ran the script did not have the pattern reader. Patterns are read in the places that run scripts: the chart's worker, the Strategy tester and the alert evaluator. A script cannot cause this; it is a fault of the platform.
Fix. Nothing in the script needs to change. Reload the chart and try again. If it comes again with the same script, send the script to support.
E-REQ-CHANGED#
Message. One of these:
data.series: the {what} must not change from bar to bar; it is built from a price or a value that moves. Use a constant, an input or symbol.*data.series: the {what} changed from "{was}" to "{now}" on bar {bar}; it must be the same on every bar of a run
Cause. The symbol or timeframe of a request is not the same on every bar. It is made from a price, a bar number, or a name that a statement of the script changes. When the script is checked the engine can tell this from the text; a value it cannot judge from the text, such as the parameter of a function, is checked when the script runs, and the message then names the bar on which it changed.
Fix. Use a constant, an input, or symbol.* for the symbol and the timeframe. These are accepted too: a let or a state that nothing writes, the names of a tuple that a function of the script returns, an if or match over such values, and a call of a function of the script on them.
indicator "Example"
edition = 1
plot(data.series(if close > open then "60" else "240", close, symbol = symbol.id))Corrected:
indicator "Example"
edition = 1
plot(data.series("60", close, symbol = symbol.id))E-REQ-LIMIT#
Message. This script reads {requests} different symbol and timeframe pairs; a host allows {maxRequests}. Read what you need once and keep it in a variable
Cause. The script reads more different symbol-and-timeframe pairs than the host allows.
Fix. Read what you need once and keep it in a variable; several expressions on one timeframe count as one pair.
indicator "Example"
edition = 1
plot(data.series("120", close, symbol = symbol.id), name = "t0")
plot(data.series("180", close, symbol = symbol.id), name = "t1")
plot(data.series("240", close, symbol = symbol.id), name = "t2")
plot(data.series("360", close, symbol = symbol.id), name = "t3")
plot(data.series("480", close, symbol = symbol.id), name = "t4")
plot(data.series("720", close, symbol = symbol.id), name = "t5")
plot(data.series("1D", close, symbol = symbol.id), name = "t6")
plot(data.series("2D", close, symbol = symbol.id), name = "t7")
plot(data.series("3D", close, symbol = symbol.id), name = "t8")
plot(data.series("1W", close, symbol = symbol.id), name = "t9")
plot(data.series("15", close, symbol = symbol.id), name = "t10")
plot(data.series("30", close, symbol = symbol.id), name = "t11")
plot(data.series("45", close, symbol = symbol.id), name = "t12")
plot(data.series("10", close, symbol = symbol.id), name = "t13")
plot(data.series("20", close, symbol = symbol.id), name = "t14")
plot(data.series("25", close, symbol = symbol.id), name = "t15")
plot(data.series("35", close, symbol = symbol.id), name = "t16")
plot(data.series("40", close, symbol = symbol.id), name = "t17")
plot(data.series("50", close, symbol = symbol.id), name = "t18")
plot(data.series("55", close, symbol = symbol.id), name = "t19")
plot(data.series("65", close, symbol = symbol.id), name = "t20")Corrected:
indicator "Example"
edition = 1
plot(data.series("60", close, symbol = symbol.id))E-REQ-UNDECLARED#
Message. data.series: "{written}" is not declared. Add it to the uses line of the script (uses "{written}")
Cause. A request names a symbol written in the script that the script has not declared with uses.
Fix. Add uses "SYMBOL" at the top. Another symbol's data is not available in this release (E4001).
indicator "Example"
edition = 1
plot(data.series("60", close, symbol = "EURUSD"))E-SESSION-DUP#
Message. a session named "{name}" is already declared
Cause. Two sessions are declared with one name, through the built-in form session.define.
Fix. Give each session its own name. The session NAME = ... form refuses a duplicate with E3101.
indicator "Example"
edition = 1
session.define("a", "0800-1600", "UTC")
session.define("a", "0900-1700", "UTC")
plot(close)Corrected:
indicator "Example"
edition = 1
session.define("a", "0800-1600", "UTC")
session.define("b", "0900-1700", "UTC")
plot(close)E-SESSION-NAME#
Message. One of these:
session: the name is empty{fn}: the session name must be written in the script, as a text{fn}: no session named "{name}" is declared abovestate session needs a session: declare one withsession NAME = …above itstate session: no session named "{name}" is declared
Cause. A session is read by a name that is not declared above.
Fix. Declare it before its first use.
indicator "Example"
edition = 1
plot(if session.active("nope") then 1 else 0)Corrected:
indicator "Example"
edition = 1
session.define("nope", "0800-1600", "UTC")
plot(if session.active("nope") then 1 else 0)E-SESSION-TEXT#
Message. One of these:
{fn}: {what} is missing{fn}: {what} must be written in the script, as a text (not read from an input or computed)session "{name}": {bad}clock.reached: "{tod}" is not a time of day (HH:MM, 00:00 to 23:59)
Cause. The hours of a session are not written in the form HHMM-HHMM.
Fix. Write "0800-1630". This built-in form takes more than the language form does; the language form is session NAME = 08:00 .. 16:30 @ zone, where the times are checked as E1020.
indicator "Example"
edition = 1
session.define("a", "banana", "UTC")
plot(close)Corrected:
indicator "Example"
edition = 1
session.define("a", "0800-1630", "UTC")
plot(close)E-SESSION-ZONE#
Message. One of these:
session "{name}": the zone "{zone}" is not one the chart knows (a name such as "Europe/London" or "America/New_York", or "UTC+3")clock.reached: the zone "{clockZone}" is not one the chart knows (a name such as "America/New_York", or "UTC+3")
Cause. A session or a clock time names a time zone the chart does not know. The language form reports it as E1022.
Fix. Use a name such as "Europe/London" or "UTC".
indicator "Example"
edition = 1
session.define("a", "0800-1600", "Mars/X")
plot(close)Corrected:
indicator "Example"
edition = 1
session.define("a", "0800-1600", "Europe/London")
plot(close)E-STATE-SESSION#
Message. state session needs the session name when the script declares more than one ({join})
Cause. state session has no name while the script declares more than one session. The language form reports it as E3280.
Fix. Name the session.
E-TF-UNKNOWN#
Message. {fn}: "{text}" is not a timeframe this chart knows. Write minutes as a number ("15", "60", "240"), or a count and a unit ("15m", "4h", "1D", "1W", "1M")
Cause. A text that names a timeframe is not one the chart can read. The functions that take a timeframe are data.series, data.intrabars, bar.time_in, bar.close_time_in, tf.changed and tf.to_seconds. A text written in the script is refused when the script is checked, with its line; for data.series, a text that is computed or comes from an input is refused on the bar where it is read. The chart's own bars are never used under another name.
Fix. Write minutes as a number, or a count and a unit: "15m" is fifteen minutes (small m), "1M" is a month (capital M).
indicator "Example"
edition = 1
plot(data.series("1hh", close, symbol = symbol.id))Corrected:
indicator "Example"
edition = 1
plot(data.series("1h", close, symbol = symbol.id))E-TS-ZONE#
Message. clock.timestamp("…") needs a zone: write 2026-09-17T07:10:00Z, or clock.timestamp("America/New_York", 2026, 9, 17, 7, 10)
Cause. timestamp("...") is given a text that has no time zone.
Fix. Add the zone to the text: clock.timestamp("2026-09-17T07:10:00Z"), or use the form with a zone name: clock.timestamp("America/New_York", 2026, 9, 17, 7, 10).
indicator "Example"
edition = 1
plot(clock.timestamp("2026-09-17 07:10"))Corrected:
indicator "Example"
edition = 1
plot(clock.timestamp("2026-09-17T07:10:00Z"))Warnings#
A warning never stops a script.
W-FTEXT-PLACEHOLDER#
Message. "{{{name}}}" in an f-text is plain text: for an alert placeholder write a plain text, or {{{{{name}}}}} in the f-text
Cause. An alert placeholder such as {{ticker}} is written in a formatted text, where the double brace means the brace itself.
Fix. Write the placeholder in a plain text, not an f-text. Alert keys and options lists the placeholders.
indicator "Example"
edition = 1
if close > open
alert.send(f"{{ticker}} up", key = "up")
plot(close)Corrected:
indicator "Example"
edition = 1
if close > open
alert.send("{{ticker}} up", key = "up")
plot(close)W-FUTURE-READ#
Message. One of these:
This read of another timeframe looks ahead (future = true) on a value that is not shifted: on the bars of a day it shows the day's final figure, which the bar did not have[, and a strategy would trade on it][, and an alert would ring on it]Could not tell whether this read looks ahead: it asks for the future (future = true) on a value the check cannot follow[. The replay found nothing that changed, so what it reads is known at the time]
Cause. A read of another timeframe asks for the future (future = true) on a value that is not shifted: on the bars of a day it shows the day's final figure.
Fix. Remove future = true, or shift the value back: high[1].
indicator "Example"
edition = 1
plot(data.series("1D", high, symbol = symbol.id, future = true))Corrected:
indicator "Example"
edition = 1
plot(data.series("1D", high[1], symbol = symbol.id, future = true))W-ID-ANON-NONASCII#
Message. A plot without a latin title or a name gets an id from its position, which changes when plots are added: add key =
Cause. A plot has no name and no Latin title, so its id comes from its position and changes when plots are added above it.
Fix. Give it a key: plot(x, key = "average", name = "...").
indicator "Example"
edition = 1
plot(tech.sma(close, 20), name = "میانگین")Corrected:
indicator "Example"
edition = 1
plot(tech.sma(close, 20), key = "average", name = "میانگین")W-ID-COLLISION#
Message. These plots share the id "{id}": the second becomes "{id}_2"; give each a key =
Cause. Two plots would get the same id from their titles. The second becomes id_2.
Fix. Give each its own key.
indicator "Example"
edition = 1
plot(close, name = "A b")
plot(open, name = "A b")Corrected:
indicator "Example"
edition = 1
plot(close, name = "A b")
plot(open, name = "Open")W-ID-LOOKALIKE#
Message. This name uses an Arabic letter that looks like a Persian one ("{found}"): write "{expected}"
Cause. A name uses an Arabic letter that looks like a Persian one (for example the Arabic Yeh for the Persian Yeh).
Fix. Write the Persian letter the warning names. The two look the same on screen but are different characters.
indicator "Example"
edition = 1
let كم = 1
plot(كم)Corrected:
indicator "Example"
edition = 1
let کم = 1
plot(کم)W-INT-BOOL#
Message. A number is used as a condition: compare it (x != 0)
Cause. A number written out, or a number input, is used as a condition (for example while 1).
Fix. Compare it: x != 0.
W-LIVE-READ#
Message. This read shows the forming bar of the other timeframe (live = true): its value moves while the bar is open
Cause. A read of another timeframe shows its forming bar (live = true), so the value moves while the bar is open.
Fix. Remove live = true unless you want a moving value for display only.
indicator "Example"
edition = 1
plot(data.series("60", close, symbol = symbol.id, live = true))Corrected:
indicator "Example"
edition = 1
plot(data.series("60", close, symbol = symbol.id))W-MATCH-OPEN#
Message. This match has no "_" arm and does not cover every case
Cause. A match has no _ case and does not cover every value, so some bars give na.
Fix. Add a last line _ => value.
indicator "Example"
edition = 1
let size = match int(close) % 2
0 => 1
1 => 2
plot(size)Corrected:
indicator "Example"
edition = 1
let size = match int(close) % 2
0 => 1
_ => 2
plot(size)W-METHOD-SHADOWS-BUILTIN#
Message. Your method "{name}" takes the place of a built-in one of the same name
Cause. A method you define takes the place of a built-in method of the same name.
Fix. Rename your method, unless replacing the built-in is what you want.
indicator "Example"
edition = 1
let xs = [1.0, 2.0]
fn array.size(self): int = 42
plot(xs.size())Corrected:
indicator "Example"
edition = 1
let xs = [1.0, 2.0]
fn array.count_all(self): int = self.size()
plot(xs.count_all())W-MUT-COUNTER#
Message. A mut starts again every bar, so this counter ends at 1: did you mean state?
Cause. A mut is set to a start value on every bar and then increased, so the counter always ends at the first step.
Fix. Use state to keep a count between bars.
indicator "Example"
edition = 1
mut count = 0
count += 1
plot(count)Corrected:
indicator "Example"
edition = 1
state count = 0
count += 1
plot(count)W-NA-COMPARE#
Message. Comparing with na is never true: use is_na(x)
Cause. A value is compared with na, which is never true.
Fix. Test with is_na(x).
indicator "Example"
edition = 1
let average = tech.sma(close, 20)
plot(if average == na then 0 else average)Corrected:
indicator "Example"
edition = 1
let average = tech.sma(close, 20)
plot(if is_na(average) then 0 else average)W-REPAINT#
Message. One of these:
What this script showed on bars that had closed is not what it shows now (first seen on bar {bar}, in {channel}): it uses bars that came after themA signal of this script came late: bars that had closed did not show it when they closed (first seen on bar {bar}, in {channel})
Cause. A check that runs the script on the bars up to a point, and again on all of them, found a closed bar whose figures changed, or a signal that came late. The check is not part of the editor in this release, so you will not meet this warning there.
Fix. Find the value that depends on a bar that comes later: a look-ahead read, a live read or a pivot. Results that look too good shows each.
W-SHADOW-BUILTIN#
Message. "{name}" hides a built-in name of the chart
Cause. A name you declare is the name of a built-in, such as the series close or a function like plot. For a series, your variable then wins and the price is out of reach; a function stays callable, but the reader cannot tell the two apart.
Fix. Choose another name.
indicator "Example"
edition = 1
let close = 1
plot(close)Corrected:
indicator "Example"
edition = 1
let level_ = 1
plot(level_)W-SHADOW-GLOBAL#
Message. "{name}" hides a name declared outside this function
Cause. A name inside a function is the name of one declared outside it. Reading the outer one is no longer possible there.
Fix. Choose another name for the inner one.
indicator "Example"
edition = 1
let level_ = 10
fn f(x: float): float
let level_ = x * 2
return level_
plot(f(close))Corrected:
indicator "Example"
edition = 1
let level_ = 10
fn f(x: float): float
let doubled = x * 2
return doubled
plot(f(close) + level_)Hints#
A hint comes with an error and says what to write instead, when the line is written in a form this language does not use. It never names a product.
W3302#
Message. {call} moves its state only on the bars where {?this if block{if}?}{?this else block{else}?}{?this match arm{match}?}{?this state initializer{state}?}{?this line{exit}?}{?this block{block}?} runs; on the other bars its state stays as it was
Cause. A call that keeps a state for the line it is written on stands in a block that may not run: an if or else block, an arm of match, the initializer of a state, or the lines after a return, break or continue that may have run. The call is legal there. Its state moves only on the bars where the block runs, and on the other bars it stays as it was.
Fix. Nothing is wrong if that is what you mean: it is the way to run a call only where it is reached. If the call should see every bar, write it first on a line of its own, above the block.
indicator "Example"
edition = 1
let trend = close > tech.sma(close, 50)
let signal = if trend
tech.crosses_above(close, tech.sma(close, 10))
else
false
plot(if signal then 1 else 0)Corrected, when the call should see every bar:
indicator "Example"
edition = 1
let trend = close > tech.sma(close, 50)
let crossed = tech.crosses_above(close, tech.sma(close, 10))
let signal = trend and crossed
plot(if signal then 1 else 0)H-FOREIGN-ARROW#
Message. This form belongs to another language: {use}
Cause. The line looks like a function written with => after its parameters, a form this language does not use.
Fix. Write fn name(args) = expression.
This hint comes with the error E2005:
indicator "Example"
edition = 1
f(x) => x * 2
plot(f(close))Corrected:
indicator "Example"
edition = 1
fn f(x: float): float = x * 2
plot(f(close))H-FOREIGN-ASSIGN#
Message. This form belongs to another language: {use}
Cause. The line gives a value with :=.
Fix. Write =. A name that changes is declared with mut or state.
This hint comes with the error E2005:
indicator "Example"
edition = 1
x := 1
plot(x)Corrected:
indicator "Example"
edition = 1
mut x = 1
x = 2
plot(x)H-FOREIGN-GENERIC#
Message. This form belongs to another language: {use}
Cause. The line makes a collection with array.new<float>(...).
Fix. Write array<float>(...), [a, b, c] or [0.0; n].
This hint comes with the error E2010:
indicator "Example"
edition = 1
let a = array.new<float>(3)
plot(1)Corrected:
indicator "Example"
edition = 1
let a = [0.0; 3]
plot(a.at(0))H-FOREIGN-HEADER#
Message. This form belongs to another language: {use}
Cause. The first line of the file is a comment that starts with //@, a line this language does not use. It is only a comment here.
Fix. Remove it, and start with the header: indicator("Title", edition = 1).
//@pragma
indicator "Example"
edition = 1
plot(close)Corrected:
indicator "Example"
edition = 1
plot(close)H-FOREIGN-INPUT#
Message. This form belongs to another language: {use}
Cause. The line declares an input as a function call, input.int(5).
Fix. Write input name: int = 5, title = "Title".
This hint comes with the error E2006:
indicator "Example"
edition = 1
let n = input.int(5)
plot(n)Corrected:
indicator "Example"
edition = 1
input n: int = 5, name = "N"
plot(n)H-FOREIGN-NAME#
Message. This name belongs to another language: {use}
Cause. The script writes a name that another language has and this one does not, such as a constant that only chose between two readings of a request. The hint says what to write here.
Fix. Write what the hint says. This hint comes with the error E3171 (a value) or E3160 (a call):
indicator "Example"
edition = 1
let g = barmerge.gaps_off
plot(close)Corrected:
indicator "Example"
edition = 1
plot(close)H-FOREIGN-STUDY#
Message. This form belongs to another language: {use}
Cause. The file starts with study(...).
Fix. Write indicator("Title", edition = 1).
This hint comes with the error E2080:
study("Example")
plot(close)Corrected:
indicator "Example"
edition = 1
plot(close)H-FOREIGN-SWITCH#
Message. This form belongs to another language: {use}
Cause. The line starts with switch, or a value is given by switch (let r = switch x), or switch(x) is written like a call. This language does not use that form.
Fix. Write match value, then one pattern => result line for each case.
This hint comes with the error E2005 when the line is let r = switch x:
indicator "Example"
edition = 1
let a = switch close
plot(a)Corrected:
indicator "Example"
edition = 1
let a = match close
_ => 1
plot(a)H-FOREIGN-TERNARY#
Message. This form belongs to another language: {use}
Cause. The line uses a ? b : c.
Fix. Write if condition then a else b.
This hint comes with the error E1004:
indicator "Example"
edition = 1
let a = close > open ? 1 : 2
plot(a)Corrected:
indicator "Example"
edition = 1
let a = if close > open then 1 else 2
plot(a)H-FOREIGN-TUPLE#
Message. This form belongs to another language: {use}
Cause. The line takes a result apart with [a, b] = f().
Fix. Write let (a, b) = f().
This hint comes with the error E2002:
indicator "Example"
edition = 1
[a, b] = f()
plot(a)Corrected:
indicator "Example"
edition = 1
fn pair(): (float, float) = (1.0, 2.0)
let (a, b) = pair()
plot(a + b)H-FOREIGN-VAR#
Message. This form belongs to another language: {use}
Cause. The line declares a name with var, a form this language does not use.
Fix. Write state name = value. For a value that is kept between evaluations of the forming bar, state live name = value.
This hint comes with the error E2005:
indicator "Example"
edition = 1
var x = 0
plot(x)Corrected:
indicator "Example"
edition = 1
state x = 0
plot(x)