Repository: freqtrade/freqtrade

Issue:
Freqtrade error - Order not found
Hi! Every once in awhile my bot dies and stops working. Can someone please tell me what is the problem?
![Screenshot from 2019-07-25 09-32-19](https://user-images.githubusercontent.com/51093905/61855802-779dca80-aec9-11e9-8fdb-e831e5843775.png)



Discussion:
I suspect this is the same issue than #2037 - but including the full stacktrace.

I hope you still have this terminal session - if you scroll up are there any other outputs (i suspect the order-creation fails too - which is the real cause of the problem). Nevertheless, this should not crash the bot and must be handled gracefully.

Hi. I have this termina session. Here is the picture.
![Screenshot from 2019-07-25 12-52-01](https://user-images.githubusercontent.com/51093905/61865091-4a5a1800-aedb-11e9-8890-0166568dbdab.png)


Resolving patch:
diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py
--- a/freqtrade/exchange/exchange.py
+++ b/freqtrade/exchange/exchange.py
@@ -174,10 +174,10 @@ def _init_ccxt(self, exchange_config: dict, ccxt_module=ccxt,
         try:
 
             api = getattr(ccxt_module, name.lower())(ex_config)
-        except (KeyError, AttributeError):
-            raise OperationalException(f'Exchange {name} is not supported')
+        except (KeyError, AttributeError) as e:
+            raise OperationalException(f'Exchange {name} is not supported') from e
         except ccxt.BaseError as e:
-            raise OperationalException(f"Initialization of ccxt failed. Reason: {e}")
+            raise OperationalException(f"Initialization of ccxt failed. Reason: {e}") from e
 
         self.set_sandbox(api, exchange_config, name)
 
@@ -398,17 +398,17 @@ def create_order(self, pair: str, ordertype: str, side: str, amount: float,
             raise DependencyException(
                 f'Insufficient funds to create {ordertype} {side} order on market {pair}.'
                 f'Tried to {side} amount {amount} at rate {rate} (total {rate * amount}).'
-                f'Message: {e}')
+                f'Message: {e}') from e
         except ccxt.InvalidOrder as e:
             raise DependencyException(
                 f'Could not create {ordertype} {side} order on market {pair}.'
                 f'Tried to {side} amount {amount} at rate {rate} (total {rate * amount}).'
-                f'Message: {e}')
+                f'Message: {e}') from e
         except (ccxt.NetworkError, ccxt.ExchangeError) as e:
             raise TemporaryError(
-                f'Could not place {side} order due to {e.__class__.__name__}. Message: {e}')
+                f'Could not place {side} order due to {e.__class__.__name__}. Message: {e}') from e
         except ccxt.BaseError as e:
-            raise OperationalException(e)
+            raise OperationalException(e) from e
 
     def buy(self, pair: str, ordertype: str, amount: float,
             rate: float, time_in_force) -> Dict:
@@ -493,9 +493,9 @@ def get_balances(self) -> dict:
             return balances
         except (ccxt.NetworkError, ccxt.ExchangeError) as e:
             raise TemporaryError(
-                f'Could not get balance due to {e.__class__.__name__}. Message: {e}')
+                f'Could not get balance due to {e.__class__.__name__}. Message: {e}') from e
         except ccxt.BaseError as e:
-            raise OperationalException(e)
+            raise OperationalException(e) from e
 
     @retrier
     def get_tickers(self) -> Dict:
@@ -504,12 +504,12 @@ def get_tickers(self) -> Dict:
         except ccxt.NotSupported as e:
             raise OperationalException(
                 f'Exchange {self._api.name} does not support fetching tickers in batch.'
-                f'Message: {e}')
+                f'Message: {e}') from e
         except (ccxt.NetworkError, ccxt.ExchangeError) as e:
             raise TemporaryError(
-                f'Could not load tickers due to {e.__class__.__name__}. Message: {e}')
+                f'Could not load tickers due to {e.__class__.__name__}. Message: {e}') from e
         except ccxt.BaseError as e:
-            raise OperationalException(e)
+            raise OperationalException(e) from e
 
     @retrier
     def get_ticker(self, pair: str, refresh: Optional[bool] = True) -> dict:
@@ -528,9 +528,9 @@ def get_ticker(self, pair: str, refresh: Optional[bool] = True) -> dict:
                 return data
             except (ccxt.NetworkError, ccxt.ExchangeError) as e:
                 raise TemporaryError(
-                    f'Could not load ticker due to {e.__class__.__name__}. Message: {e}')
+                    f'Could not load ticker due to {e.__class__.__name__}. Message: {e}') from e
             except ccxt.BaseError as e:
-                raise OperationalException(e)
+                raise OperationalException(e) from e
         else:
             logger.info("returning cached ticker-data for %s", pair)
             return self._cached_ticker[pair]
@@ -651,12 +651,12 @@ async def _async_get_candle_history(self, pair: str, ticker_interval: str,
         except ccxt.NotSupported as e:
             raise OperationalException(
                 f'Exchange {self._api.name} does not support fetching historical candlestick data.'
-                f'Message: {e}')
+                f'Message: {e}') from e
         except (ccxt.NetworkError, ccxt.ExchangeError) as e:
-            raise TemporaryError(
-                f'Could not load ticker history due to {e.__class__.__name__}. Message: {e}')
+            raise TemporaryError(f'Could not load ticker history due to {e.__class__.__name__}. '
+                                 f'Message: {e}') from e
         except ccxt.BaseError as e:
-            raise OperationalException(f'Could not fetch ticker data. Msg: {e}')
+            raise OperationalException(f'Could not fetch ticker data. Msg: {e}') from e
 
     @retrier
     def cancel_order(self, order_id: str, pair: str) -> None:
@@ -667,12 +667,12 @@ def cancel_order(self, order_id: str, pair: str) -> None:
             return self._api.cancel_order(order_id, pair)
         except ccxt.InvalidOrder as e:
             raise InvalidOrderException(
-                f'Could not cancel order. Message: {e}')
+                f'Could not cancel order. Message: {e}') from e
         except (ccxt.NetworkError, ccxt.ExchangeError) as e:
             raise TemporaryError(
-                f'Could not cancel order due to {e.__class__.__name__}. Message: {e}')
+                f'Could not cancel order due to {e.__class__.__name__}. Message: {e}') from e
         except ccxt.BaseError as e:
-            raise OperationalException(e)
+            raise OperationalException(e) from e
 
     @retrier
     def get_order(self, order_id: str, pair: str) -> Dict:
@@ -683,12 +683,12 @@ def get_order(self, order_id: str, pair: str) -> Dict:
             return self._api.fetch_order(order_id, pair)
         except ccxt.InvalidOrder as e:
             raise InvalidOrderException(
-                f'Tried to get an invalid order (id: {order_id}). Message: {e}')
+                f'Tried to get an invalid order (id: {order_id}). Message: {e}') from e
         except (ccxt.NetworkError, ccxt.ExchangeError) as e:
             raise TemporaryError(
-                f'Could not get order due to {e.__class__.__name__}. Message: {e}')
+                f'Could not get order due to {e.__class__.__name__}. Message: {e}') from e
         except ccxt.BaseError as e:
-            raise OperationalException(e)
+            raise OperationalException(e) from e
 
     @retrier
     def get_order_book(self, pair: str, limit: int = 100) -> dict:
@@ -704,12 +704,12 @@ def get_order_book(self, pair: str, limit: int = 100) -> dict:
         except ccxt.NotSupported as e:
             raise OperationalException(
                 f'Exchange {self._api.name} does not support fetching order book.'
-                f'Message: {e}')
+                f'Message: {e}') from e
         except (ccxt.NetworkError, ccxt.ExchangeError) as e:
             raise TemporaryError(
-                f'Could not get order book due to {e.__class__.__name__}. Message: {e}')
+                f'Could not get order book due to {e.__class__.__name__}. Message: {e}') from e
         except ccxt.BaseError as e:
-            raise OperationalException(e)
+            raise OperationalException(e) from e
 
     @retrier
     def get_trades_for_order(self, order_id: str, pair: str, since: datetime) -> List:
@@ -726,9 +726,9 @@ def get_trades_for_order(self, order_id: str, pair: str, since: datetime) -> Lis
 
         except ccxt.NetworkError as e:
             raise TemporaryError(
-                f'Could not get trades due to networking error. Message: {e}')
+                f'Could not get trades due to networking error. Message: {e}') from e
         except ccxt.BaseError as e:
-            raise OperationalException(e)
+            raise OperationalException(e) from e
 
     @retrier
     def get_fee(self, symbol='ETH/BTC', type='', side='', amount=1,
@@ -742,9 +742,9 @@ def get_fee(self, symbol='ETH/BTC', type='', side='', amount=1,
                                            price=price, takerOrMaker=taker_or_maker)['rate']
         except (ccxt.NetworkError, ccxt.ExchangeError) as e:
             raise TemporaryError(
-                f'Could not get fee info due to {e.__class__.__name__}. Message: {e}')
+                f'Could not get fee info due to {e.__class__.__name__}. Message: {e}') from e
         except ccxt.BaseError as e:
-            raise OperationalException(e)
+            raise OperationalException(e) from e
 
 
 def is_exchange_bad(exchange: str) -> bool:
diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py
--- a/freqtrade/freqtradebot.py
+++ b/freqtrade/freqtradebot.py
@@ -524,7 +524,11 @@ def update_trade_state(self, trade, action_order: dict = None):
         if trade.open_order_id:
             # Update trade with order values
             logger.info('Found open order for %s', trade)
-            order = action_order or self.exchange.get_order(trade.open_order_id, trade.pair)
+            try:
+                order = action_order or self.exchange.get_order(trade.open_order_id, trade.pair)
+            except InvalidOrderException as exception:
+                logger.warning('Unable to fetch order %s: %s', trade.open_order_id, exception)
+                return
             # Try update amount (binance-fix)
             try:
                 new_amount = self.get_real_amount(trade, order)
@@ -749,7 +753,7 @@ def check_handle_timedout(self) -> None:
                 if not trade.open_order_id:
                     continue
                 order = self.exchange.get_order(trade.open_order_id, trade.pair)
-            except (RequestException, DependencyException):
+            except (RequestException, DependencyException, InvalidOrderException):
                 logger.info(
                     'Cannot query order for %s due to %s',
                     trade,


Test patch:
diff --git a/freqtrade/tests/test_freqtradebot.py b/freqtrade/tests/test_freqtradebot.py
--- a/freqtrade/tests/test_freqtradebot.py
+++ b/freqtrade/tests/test_freqtradebot.py
@@ -1460,6 +1460,22 @@ def test_update_trade_state_exception(mocker, default_conf,
     assert log_has('Could not update trade amount: ', caplog.record_tuples)
 
 
+def test_update_trade_state_orderexception(mocker, default_conf, caplog) -> None:
+    freqtrade = get_patched_freqtradebot(mocker, default_conf)
+    mocker.patch('freqtrade.exchange.Exchange.get_order',
+                 MagicMock(side_effect=InvalidOrderException))
+
+    trade = MagicMock()
+    trade.open_order_id = '123'
+    trade.open_fee = 0.001
+
+    # Test raise of OperationalException exception
+    grm_mock = mocker.patch("freqtrade.freqtradebot.FreqtradeBot.get_real_amount", MagicMock())
+    freqtrade.update_trade_state(trade)
+    assert grm_mock.call_count == 0
+    assert log_has(f'Unable to fetch order {trade.open_order_id}: ', caplog.record_tuples)
+
+
 def test_update_trade_state_sell(default_conf, trades_for_order, limit_sell_order, mocker):
     mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=trades_for_order)
     # get_order should not be called!!