Quick Answer
CS0103: The name 'x' does not exist in the current context means the C# compiler cannot find anything called x at the line where you use it. The name may be misspelled, declared in another place, declared inside a block that has already ended, or it may come from another language, for example _Symbol from MQL5 or close from Pine Script.
In a cBot the most common cause is an indicator or a variable created as a local variable in OnStart() and then used in OnBar(). Make it a private field of the class, assign it in OnStart(), and the error goes away. The other causes are listed below, with a checklist at the end.
From the author: I build cBots and indicators in cTrader Automate, and I convert strategies from Pine Script and MQL5 to C#. CS0103 is a good error to learn properly. The message is short, the compiler gives you the line, and almost every case comes down to scope, spelling, a missing
using, or a name that belongs to another platform. That is why this guide ends with a checklist you can run on your own code.
Key Facts
| What you see | Usual cause | Fix |
|---|---|---|
| A variable or indicator used in OnBar() that was created in OnStart() | It is a local variable, so it only exists inside OnStart() | Declare it as a private field of the class |
| A variable used after the { } block where it was declared | Block scope: it ends at the closing brace | Declare it before the block |
| Math, Convert or Environment not found | The using System; line is missing | Add using System; at the top |
| symbolName, closes, Ema | C# is case-sensitive, so the spelling must match exactly | Use the exact name, for example SymbolName |
| _Symbol, iClose, close, ta.ema | A name from MQL5 or Pine Script | Use the cTrader equivalent (table below) |
| A [Parameter] used under another name | The property has a different name than the one you typed | Use the property name |
| The same error on many lines | One missing declaration used many times | Fix the first error and build again |
What the Compiler Is Telling You
The build output shows the error code, the message with the name in quotes, and the line where the name is used. For example:
CS0103: The name 'ema' does not exist in the current context
Two things matter here:
- The name in quotes is the exact text the compiler could not find. Search for it in your file.
- The line is where the name is used, not where it should have been declared. The missing declaration can be anywhere above, or in another method.
The Broken cBot
This cBot reads an EMA once per bar and prints a message. It does not place trades. It has one error, and it is the most common one:
using cAlgo.API;
using cAlgo.API.Indicators;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class BrokenBot : Robot
{
[Parameter("EMA period", DefaultValue = 20, MinValue = 1)]
public int EmaPeriod { get; set; }
protected override void OnStart()
{
var ema = Indicators.ExponentialMovingAverage(Bars.ClosePrices, EmaPeriod);
}
protected override void OnBar()
{
double value = ema.Result.Last(1);
if (Bars.ClosePrices.Last(1) > value)
Print("Close is above the EMA");
}
}
}
The compiler reports CS0103: The name 'ema' does not exist in the current context on the line inside OnBar(). The variable ema is created inside OnStart(), so it lives only until that method ends. OnBar() is a different method and cannot see it.
Cause 1: A Local Variable Used in Another Method
This is the case above. Variables that must live between method calls, such as indicators, belong in fields. Declare the field at class level and assign it in OnStart():
private ExponentialMovingAverage _ema;
protected override void OnStart()
{
_ema = Indicators.ExponentialMovingAverage(Bars.ClosePrices, EmaPeriod);
}
Create the indicator once in OnStart(), not in OnBar(). Creating it on every bar wastes time and starts the calculation again each time.
Cause 2: The Variable Is Out of Scope
A variable declared inside { } exists only inside those braces:
if (Bars.ClosePrices.Last(1) > Bars.ClosePrices.Last(2))
{
double gap = Bars.ClosePrices.Last(1) - Bars.ClosePrices.Last(2);
}
Print(gap); // CS0103: the block that declared 'gap' has ended
Declare the variable before the block and assign it inside:
double gap = 0;
if (Bars.ClosePrices.Last(1) > Bars.ClosePrices.Last(2))
{
gap = Bars.ClosePrices.Last(1) - Bars.ClosePrices.Last(2);
}
Print(gap);
The same rule applies to for, foreach, try, switch and lambda bodies.
Cause 3: A Missing using Directive
Names such as Math, Convert and Environment live in the System namespace. If using System; is not at the top of the file, using one of them gives CS0103:
double distance = Math.Abs(Bars.ClosePrices.Last(1) - Bars.ClosePrices.Last(2)); // CS0103 without 'using System;'
Add the line at the top of the file:
using System;
You can also write the full name, System.Math.Abs(...), without the using. When the missing thing is a type you use in a declaration, such as List<int>, the compiler reports a different error (CS0246). See the table further down.
Cause 4: Spelling and Case
C# treats SymbolName and symbolName as two different names. This is a common slip when you type from memory:
Print(symbolName); // CS0103: the property is called SymbolName
Print(SymbolName); // correct
The same applies to your own fields. If you declared _ema, then _Ema and ema do not exist. A consistent naming habit, such as _camelCase for private fields, makes these slips easier to see.
Cause 5: Names From MQL5 or Pine Script
When you convert a strategy by hand, MQL5 and Pine names often stay in the code. The C# compiler has never heard of them. Common replacements:
| In MQL5 or Pine Script | In cTrader C# |
|---|---|
| _Symbol | SymbolName |
| _Period | TimeFrame |
| close[1], iClose(_Symbol, _Period, 1) | Bars.ClosePrices.Last(1) |
| PositionsTotal() | Positions.Count |
| AccountInfoDouble(ACCOUNT_BALANCE) | Account.Balance |
| SymbolInfoDouble(_Symbol, SYMBOL_ASK) | Symbol.Ask |
| ta.ema(close, 20) | Indicators.ExponentialMovingAverage(Bars.ClosePrices, 20) |
Shift numbers also differ between platforms. How Last(1) relates to Pine's [1] is explained in Pine Script to cTrader C#: How a Strategy Becomes a cBot.
Cause 6: A Parameter Used Under Another Name
A [Parameter] is a property, and the code must use the property name, not the text in the attribute and not a name you made up:
[Parameter("EMA period", DefaultValue = 20, MinValue = 1)]
public int EmaPeriod { get; set; }
// Print(emaPeriod); // CS0103: the property is called EmaPeriod (capital E)
// Print("EMA period"); // prints the text, it does not read the parameter
Print(EmaPeriod); // correct
The text in quotes is the label shown in the parameters panel. The name after public int is what you use in code.
Cause 7: One Missing Name, Many Errors
If the same missing name is used on ten lines, the compiler can report ten errors. Fix the declaration once and build again before you touch anything else. Do the same when the error list is long: start with the first error, because later errors are often a result of it.
The Fixed cBot
This version fixes the scope problem, adds using System; for Math, and uses an exact name for every member:
using System;
using cAlgo.API;
using cAlgo.API.Indicators;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class FixedBot : Robot
{
[Parameter("EMA period", DefaultValue = 20, MinValue = 1)]
public int EmaPeriod { get; set; }
private ExponentialMovingAverage _ema;
protected override void OnStart()
{
_ema = Indicators.ExponentialMovingAverage(Bars.ClosePrices, EmaPeriod);
}
protected override void OnBar()
{
// Last(1) is the last closed bar, Last(2) the bar before it
double close1 = Bars.ClosePrices.Last(1);
double close2 = Bars.ClosePrices.Last(2);
double emaValue = _ema.Result.Last(1);
double distance = Math.Abs(close1 - close2);
if (close1 > emaValue)
Print("{0}: close {1} is above the EMA {2}. Last move: {3}", SymbolName, close1, emaValue, distance);
}
}
}
The bot only prints a message, so you can check the numbers against your chart before you add any trading logic.
CS0103 and Similar Errors
These messages look alike, but they point to different problems:
| Error | Message | Usual cause |
|---|---|---|
| CS0103 | The name 'x' does not exist in the current context | A variable, method or class name that is not declared, out of scope, or misspelled |
| CS0246 | The type or namespace name 'X' could not be found | A type used in a declaration, with a missing using or reference (for example List<int>) |
| CS1061 | 'X' does not contain a definition for 'y' | The object exists, but the member name after the dot is wrong |
| CS0841 | Cannot use local variable 'x' before it is declared | The variable is in the same scope, but used above its declaration line |
Checklist: What to Check When You See CS0103
A cBot that builds is not yet a cBot that is correct, but you cannot test anything until it builds. Go through these steps in order:
- Read the name in quotes and the line number. Search for the exact name in the file, with the same case.
- Find where it should be declared. If it never is, declare it. If it is declared, check the next steps.
- Check the method. A variable declared in
OnStart()cannot be used inOnBar(). Move it to a private field. - Check the braces. Is the declaration inside an
if,forortryblock that has already closed before the line with the error? - Check the spelling and the case of the declaration and of every use.
- Check the top of the file. For
Math,Convertand other .NET names,using System;must be there. - Look for names from another platform. Anything with a leading underscore like
_Symbol, anything that looks likeiClose(...)orta., is not C#. - Fix one error and build again. Do not edit ten places at once.
- When it builds, run a backtest on a short period. Compare the first few signals with your source strategy before you look at any totals.
Common Mistakes
- Declaring an indicator in
OnStart()asvarand using it inOnBar(). It needs to be a field. - Declaring a variable inside an
ifblock and using it after the block. - Forgetting
using System;after copying only a part of a cBot into a new file. - Typing
symbolNameorclosePriceswhere the member isSymbolNameorClosePrices. - Leaving MQL5 or Pine names in converted code, such as
_Symbol,iCloseorclose. - Using the label of a
[Parameter]instead of the property name. - Fixing the last error first. Start from the first one, because the others are often a result of it.
FAQ
Related Guides
- MQL5 undeclared identifier error: the same kind of error in MetaEditor, with its causes.
- Pine Script to cTrader C#: How a Strategy Becomes a cBot: map bars, indicators and entries, and avoid the shift mistakes.
- Pine Script to MQL5 guide: the same conversion steps for MetaTrader.
- What to check in a trading bot before going live: a pre-live checklist for stops, lot size, spread and trade results
- MQL5 array out of range error: causes and a safe fix
Fix Compile Errors Without Guessing
If a cBot or an Expert Advisor does not build, paste the code and the error message into the CodeFlowOS Error Fixer. It suggests a minimal fix, explains each error and shows what changed. A fix uses 1 credit, with up to 3 attempts included, and the compiler check is optional. Outputs are not guaranteed, and code that compiles can still have wrong trading logic, so always review the result. Before a bot goes live, the Code Review is free during the early-bird period. CodeFlowOS also converts strategies between Pine Script, MQL5 and cTrader C#: try the converter page.
This article is educational. It does not describe trading performance and is not financial advice. Always build the code in cTrader Automate and backtest it before using it on a live account.