SuperCharting
Sign in Get started Account Open charts

Learn / Pine Script errors

Pine Script error: Cannot modify global variable in function (fix)

How to fix the Pine Script error "Cannot modify global variable in function": return the value instead, or keep the state in an array or object.

TradingView shows "Cannot modify global variable '<name>' in function" when a function you wrote uses := on a variable that was declared outside it, at the top level of the script. Pine lets a function read global variables, but it will not let the function reassign them. The quick fix is to have the function return the new value and do the := at global scope.

What causes it

The rule is simple: inside a function body, := (and the shortcuts built on it, such as += and -=) may only touch variables that the function itself declared. A global variable is off limits for reassignment, even when it is declared with var.

The classic case is a counter. You want a helper that bumps a running total, so you write a small function and call it on each bar. This code FAILS on TradingView:

//@version=6
indicator("Global")
var count = 0
bump() =>
    count := count + 1
bump()
plot(count)

The error points at the line count := count + 1. The same thing happens with count += 1 inside the function, because += is a reassignment too.

It also shows up when a script is split into functions after the fact. Code that worked at the top level, where := on a global is allowed, stops compiling once it is moved into a function body, even though not a single character changed.

Reading a global inside a function is fine. A function such as isAbove() => close > someGlobal compiles, because it only reads the value.

How to fix it

There are two clean ways out. Which one you pick depends on whether the function needs to change one value or a whole set of state.

Return the value and assign it at global scope

Let the function do the thinking and give back a result. Then the global variable is changed at the top level, where Pine allows it. In this tested version the function only answers a question, and the counter is updated outside it:

//@version=6
indicator("Count bars above EMA")
var int count = 0
above(src, len) =>
    src > ta.ema(src, len)
if above(close, 20)
    count += 1
plot(count, "Bars above EMA 20")

When the function has to produce the new value itself, pass the old value in as an argument and return the updated one:

//@version=6
indicator("Return, then assign")
var float total = 0.0
addBody(prev, o, c) =>
    prev + (c - o)
total := addBody(total, open, close)
plot(total, "Running sum of candle bodies")

The := sits on the global line total := addBody(...), so Pine is happy.

Keep the state in an array, matrix, map or object

Sometimes you want the function to update state directly, for example when several helpers share one store. Put the state in an array, matrix, map or user-defined type object. The function then changes the contents of that container, and the global variable itself (the reference to the container) is never reassigned. Tested version:

//@version=6
indicator("Counter in an array")
var counter = array.from(0)
bump(arr) =>
    array.set(arr, 0, array.get(arr, 0) + 1)
if close > open
    bump(counter)
plot(array.get(counter, 0), "Green bars")

array.set() writes into the array; it never uses := on counter, and that is why Pine accepts it. A user-defined type works the same way: pass the object in and set its fields inside the function. The variable that holds the object keeps pointing at the same object, so Pine allows it.

Use the return approach for one or two values, since it keeps the data flow easy to read. Reach for a container when the state is larger or shared between several functions.

What SuperCharting's Script Editor shows

SuperCharting's engine is more lenient here and runs this code. The broken counter example above compiles and runs on sample bars without an error in the console. If the script must also work on TradingView, fix it the way shown above. Both tested fixes run in SuperCharting as well, so you can use the same script in both places.

To check a script yourself:

  1. Open a chart and open the Script Editor with Ctrl + E.
  2. Paste the script into the code area.
  3. Read the console for compile errors, then press Add to chart to run it on real bars.

The Pine Script code checker page explains the two checks and the Auto-fix button in more detail. Because SuperCharting does not stop on this pattern, a clean console here is no proof that TradingView will accept the script; read your functions for := on globals before you copy the code across.

If you moved a variable into a block to get around this error and now it cannot be found, see Undeclared identifier. If the function also calls plot(), you will hit Cannot use 'plot' in local scope next. For the basics of = versus :=, read Pine Script v6 basics.

Frequently asked questions

Does declaring the variable with var fix it?

No. var only means the variable keeps its value from bar to bar. It is still a global variable, and a function still cannot reassign it with :=.

Can a function read a global variable?

Yes. Reading is allowed. Only reassigning with :=, +=, -= and the other assignment shortcuts is blocked inside a function.

Why does the array version work when the plain variable does not?

The function changes what is inside the array, and the variable counter keeps pointing at the same array the whole time. Pine only blocks reassigning the global variable itself.

Which fix should I use?

Return the value when the function works out one result. Use an array, matrix, map or object when several functions share the same state or there is too much of it to pass back and forth.

TradingView and Pine Script are trademarks of TradingView, Inc. SuperCharting is independent and not affiliated with it.

Try it on a live chart

SuperCharting is an AI-enabled charting and coding platform in your browser: charts, Pine-compatible scripts with AI Auto-fix, the Strategy Tester, alerts and the screener.

Create a free account More guides