Generate code in 3 minutes
Enter your idea and AI generates runnable code.
To check if a trade failed to open in MQL4, you must evaluate the return value of the OrderSend() function. If OrderSend() returns -1, the trade failed. Immediately after detecting a failure, you call GetLastError() to retrieve the specific error code.
Here is the standard implementation pattern for robust error checking.
//+------------------------------------------------------------------+
//| Function to open a trade with error checking |
//+------------------------------------------------------------------+
void OpenBuyOrder(double volume, int slippage, double sl, double tp)
{
// 1. Reset the last error variable before the operation
ResetLastError();
// 2. Attempt to send the order
int ticket = OrderSend(Symbol(), OP_BUY, volume, Ask, slippage, sl, tp, "My Buy Order", 0, 0, clrGreen);
// 3. Check the return value
if(ticket < 0)
{
// 4. Retrieve the specific error code
int errorCode = GetLastError();
// 5. Log the error for analysis
Print("OrderSend failed. Error Code: ", errorCode, " Description: ", GetErrorDescription(errorCode));
// Optional: Handle specific errors programmatically
if(errorCode == ERR_NOT_ENOUGH_MONEY) {
Print("Critical: Insufficient funds to open trade.");
}
else if(errorCode == ERR_REQUOTE) {
Print("Warning: Price changed (Requote). Consider increasing slippage or retrying.");
}
}
else
{
Print("Order opened successfully. Ticket #", ticket);
}
}
//+------------------------------------------------------------------+
//| Helper function to translate common error codes to text |
//+------------------------------------------------------------------+
string GetErrorDescription(int errCode)
{
switch(errCode)
{
case 0: return("No error");
case 2: return("Common error");
case 64: return("Account disabled");
case 128: return("Trade timeout");
case 129: return("Invalid price");
case 130: return("Invalid stops");
case 131: return("Invalid trade volume");
case 132: return("Market is closed");
case 133: return("Trade is disabled");
case 134: return("Not enough money");
case 135: return("Price changed");
case 136: return("Off quotes");
case 138: return("Requote");
case 146: return("Trade context is busy");
case 148: return("Too many orders");
default: return("Unknown error");
}
}
ResetLastError(): Always call this before OrderSend. If you don't, GetLastError() might return an old error code from a previous operation, leading to confusion.OrderSend returns the ticket number (int) if successful. If it fails, it returns -1.GetLastError(): This system function returns the code of the last error that occurred. It resets to 0 after being called, so store it in a variable (like errorCode in the example) if you need to use it multiple times in your logic.When debugging, these are the most frequent codes you will encounter:
RefreshRates() before sending the order.MODE_STOPLEVEL) or calculated incorrectly.Sleep() to handle this.Q: Can I automatically retry the trade if it fails?
A: Yes, but only for specific errors. You should implement a retry loop for "transient" errors like 138 (Requote) or 146 (Trade Context Busy). Do not retry immediately for logical errors like 134 (Not Enough Money) or 130 (Invalid Stops), as these will fail indefinitely until parameters are changed.
Q: Why do I get Error 130 (Invalid Stops) even when my math seems correct?
A: This often happens if you do not normalize the price. Always wrap your calculated SL/TP prices in NormalizeDouble(price, Digits). Also, check MarketInfo(Symbol(), MODE_STOPLEVEL) to ensure your stops are not too close to the entry price.
Q: Does GetLastError() work in the Strategy Tester?
A: Yes, it works exactly the same way in the Strategy Tester as it does in live trading, which is essential for debugging your strategy logic before going live.