Skip to main content

Undeclared Identifier Error in Pine Script: 3 Causes and Fixes

· 12 min read
Pineify Team
Pine Script and AI trading workflow research team

You're staring at the Pine Script editor. Line 37 has a red squiggle. The error panel says "undeclared identifier." Your indicator won't compile.

An undeclared identifier error in Pine Script means the compiler encountered a name it doesn't recognize -- a variable you never declared, a function you misspelled, or something you referenced outside its reachable scope. Every identifier must be declared before use, spelled correctly, and accessible from the line that references it.

I hit this error three times last week building a multi-timeframe screener for BTCUSD on the 15-minute chart. Each one had a different root cause: a typo on barssince instead of ta.barssince(), a variable trapped inside an if block, and a security() call written for Pine Script v3 that v5 flat-out rejected.

Here's the good news: this error is precise. Pine Script tells you exactly which name it cannot find and on which line. Three causes cover almost every case.

The 3 Causes of Undeclared Identifier Errors

1. Using a Variable Before Declaring It

You reference mySmaValue in a plot() call, but mySmaValue was never declared. Pine Script doesn't guess what you meant. It just tells you the name is unknown.

This is the most common cause. You wrote the plot line first, planned to fill the calculation later, and forgot. Or you declared the variable further down in the file where the compiler hadn't reached it yet. Pine Script compiles top to bottom -- the declaration must come before the first usage. If the concept of variable declaration is new, the beginners guide to Pine Script covers the absolute basics first.

2. Scope Boundaries

Variables declared inside a block -- an if statement, a for loop, a function -- live only inside that block. Reference them one line outside and Pine Script treats them as undeclared.

This trips me up constantly. Last November I was building an AAPL volatility tracker. I declared float atrValue = na at the top of the script. Inside an if block I wrote atrValue = ta.atr(14) using = instead of :=. Pine Script treated that as a brand new local variable, and the outer atrValue stayed na for every bar.

3. Version Mismatches

Pine Script v5 restructured how built-in functions and variables are named. study() became indicator(). security() became request.security(). sma() became ta.sma(). Color values went from bare red to color.red.

Copy-paste a 2019 forum post into a v5 editor and you'll get undeclared identifier errors on nearly every line. I've done this more times than I want to count. The code looks right because it worked in v3, but v5 simply doesn't ship those old function names.

Step-by-Step Fixes

I've spent hundreds of hours debugging these errors. Here's the sequence I run through, with why each step works and what can still go wrong.

Fix #1: Declare Before Reference

Declare every variable before any line that uses it. Put declarations at the top of the script where the compiler can find them.

//@version=5
indicator("My Indicator", overlay=true)

// Declare variables at the top
var float mySignal = na
var int barCount = 0

// Now use them in your logic
if close > open
mySignal := close - open
barCount += 1

plot(mySignal, title="Signal", color=color.blue)

Why this works: Pine Script compiles top to bottom in each execution pass. A variable must exist in the symbol table before any expression tries to look it up. Putting declarations at the top guarantees they get registered first.

What can go wrong: var initializes a variable once on the first bar and preserves its value across bars. If you meant to reset the value on each new bar, use plain assignment (mySignal = na) inside your calculation block. I prefer var for accumulators and counters, but I've definitely overused it and ended up with stale values that took an hour to track down.

Fix #2: Respect Scope Boundaries

Declare the variable at the highest scope where it needs to be accessible, then modify it inside blocks using the := reassignment operator.

// Wrong way - variable trapped in if block
if close > open
float myVar = close - open // This won't work outside the if statement

// Right way - declare outside, modify inside
float myVar = na
if close > open
myVar := close - open // Use := to modify existing variable

plot(myVar)

Why this works: na is Pine Script's "not available" value. Declaring the variable at the top level with na creates a slot every block can see. The := operator reassigns that same variable instead of creating a new local one.

What can go wrong: na in a plot() means nothing draws until the variable gets a real value. If your if condition rarely triggers, you'll get gaps in the plotted line. I sometimes use float myVar = 0 as the initial value instead. That avoids plot gaps, but it can silently misrepresent data when the condition hasn't fired yet.

Fix #3: Update Legacy Syntax

When you inherit code from an older Pine Script version, translate the old function names to their v5 equivalents. The Pine Script v6 guide covers all the recent changes.

The most common conversions:

  • study() becomes indicator()
  • tickerid becomes syminfo.tickerid
  • security() becomes request.security()
  • color.red replaces bare red
  • input.int() replaces input()

Why this works: Pine Script v5 removed the old global function names. Using the new namespaced versions is the only way the compiler will recognize these identifiers in a v5 script.

What can go wrong: Some v3/v4 functions don't have a direct v5 equivalent. security() to request.security() changes the parameter order slightly -- I've missed this before and got a different data series than expected. If you're migrating a script longer than 500 lines, test bar by bar with a small data set first.

Fix #4: Check Namespace Prefixes

Pine Script v5 organized built-in functions into namespaces. If you're still calling sma() without the ta. prefix, v5 will reject it.

Common namespace changes:

  • Math functions: abs() becomes math.abs()
  • Technical indicators: sma() becomes ta.sma()
  • Array operations: array.new_float() (was already namespaced)
  • Strategy functions: strategy.entry() (was already namespaced)

Why this works: Namespaces group related functions and reduce name collisions. The ta. prefix signals the compiler to look in the technical-analysis function group.

What can go wrong: Some functions existed in both v4 and v5 with the same name -- array.new_float() for example. Others got split or deprecated. I haven't tested every single v4 function in v5, so when in doubt, check the TradingView Pine Script reference before assuming the old name still works.

Pineify | Best Pine Script Generator

Fix #5: Use the Pine Script Debugger

Pine Script has a few built-in debugging tricks that help narrow down undeclared identifier errors.

// Use this to check if variables are being set correctly
if barstate.islast
label.new(bar_index, high, text="Debug: " + str.tostring(myVar))

Why this works: This label prints the current value of myVar on the last bar. If the label shows na, the variable was never assigned a real value -- which often points to a scope or declaration problem.

What can go wrong: This only checks the last bar. A variable might get set correctly on some bars and not on others. I always pair this with plot(myVar) to see the full series. Also, if myVar itself is undeclared, the compiler will catch it here too -- which is actually helpful because it isolates the problematic line.

Prevention

After years of dealing with these errors, here's what I do to avoid them:

  1. Start with a template -- I always begin with the same basic structure so I never forget the version declaration and boilerplate.
  2. Declare variables in sections -- inputs first, then intermediate calculations, then plots. Nothing gets buried.
  3. Use descriptive names -- rsi14Value instead of r or x. The name itself documents the intent.
  4. Test incrementally -- I write no more than 20 lines before hitting "Add to Chart" to verify the script compiles.

Tools like AI Pine Script generators can help skip the boilerplate, but knowing how to manually fix these errors is still critical because generated code can produce them too if the prompt has ambiguity.

Frequently Asked Questions

What does 'undeclared identifier' mean in Pine Script?

It means you referenced a variable or function name that Pine Script cannot find. This happens when you use a name before declaring it, misspell a built-in identifier, or try to access a variable declared in a different scope -- like inside an if block that the current line sits outside of.

How do I fix an undeclared identifier error caused by variable scope in Pine Script?

Declare the variable outside the block where you need to use it, then modify its value inside the block with the := operator. Write float myVar = na at the top level, then inside your if block write myVar := close - open. The := operator tells Pine Script you're modifying the outer variable, not creating a new local one.

Why does old Pine Script code cause undeclared identifier errors in v5?

Pine Script v5 renamed many functions and moved them into namespaces. sma() became ta.sma(), security() became request.security(), and study() became indicator(). Code written for v3 or v4 uses the old names, which v5 doesn't ship. The compiler sees each old name as an undeclared identifier.

Can typos cause undeclared identifier errors in Pine Script?

Yes, and they're one of the most frequent causes. Pine Script treats cloze and close as completely different identifiers. Since cloze is not a built-in, it throws an undeclared identifier error. Always scan for common misspellings: voume instead of volume, lenght instead of length, barssince instead of ta.barssince().

What is the difference between `=` and `:=` in Pine Script?

= declares and initializes a new variable. := reassigns an existing variable. If you use = inside a block on a variable that was declared outside, Pine Script creates a new local variable with the same name -- the outer variable stays unchanged. This is one of the most common scope-related gotchas.

How do I check which Pine Script version a script was written for?

Look at the first line: //@version=5 means v5, //@version=4 means v4, and so on. If there's no version comment, Pine Script defaults to v1. Scripts that call functions like sma() without the ta. prefix, or use red instead of color.red, are likely v3 or v4 code that will trigger undeclared identifier errors when compiled as v5.