I am encountering a persistent Invalid 'api_key' or 'access_token' error when trying to place an order from a long-running asynchronous Python application. I am confident my api_key and api_secret are correct because a separate, simple synchronous test script works perfectly. The issue only occurs in my main asyncio-based trading bot, and I have exhausted all logical solutions related to code structure and state management.
My main application (trading_bot.py) successfully authenticates, generates an access_token, and runs its logic. However, when it tries to place an order (sometimes minutes after authentication), the call to kite.place_order() fails with an Invalid access_token error.
The paradox is that a minimal, synchronous test script (test_fno_order.py) using the exact same credentials and configuration can successfully authenticate and place an F&O order every single time.
This suggests the issue is not with the credentials themselves, but a subtle interaction between the KiteConnect session and the asyncio event loop/threading model in a long-running application.
Environment Details
Library: kiteconnect-python (latest version) Language: Python 3.11.12 Framework: asyncio Platform: macOS Error Log & Traceback The following log appears consistently. Note the diagnostic message confirming the token being used, followed by the immediate API rejection.
2025-06-18 12:13:01,948 - INFO - PRIMARY SIGNAL 'SELL' detected, proceeding with trade. 2025-06-18 12:13:02,123 - INFO - Trade details calculated: Symbol=NIFTY2561924800PE, LotSize=75, Quantity=150 2025-06-18 12:13:02,124 - INFO - Placing LIVE order -> {'tradingsymbol': 'NIFTY2561924800PE', ...} 2025-06-18 12:13:02,124 - INFO - Re-authenticating original Kite session before placing order... 2025-06-18 12:13:02,124 - INFO - DIAGNOSTIC: Token being used for trade: C6BSdYxDZzK10vUi2nD4yJIMUjE5hVRI 2025-06-18 12:13:02,320 - ERROR - Failed to place live order for NIFTY2561924800PE: Invalid `api_key` or `access_token`. Traceback (most recent call last): File "/Users/userName/Desktop/zerodha-trading-bot/agents.py", line 58, in place_trade order_id = await asyncio.to_thread(self.kite.place_order, **order_params) File "/Users/userName/Desktop/zerodha-trading-bot/trade_bot/lib/python3.11/site-packages/kiteconnect/connect.py", line 937, in _request raise exp(data["message"], code=r.status_code) kiteconnect.exceptions.InputException: Invalid `api_key` or `access_token`. Solutions Already Attempted (Without Success)
I have tried multiple robust solutions to ensure the KiteConnect object state is valid, but all result in the same error:
Explicit set_access_token(): Ensured kite.set_access_token() is called immediately after generate_session(). Deferred Initialization: Re-architected the application to initialize the OrderExecutionAgent only after a successful authentication, passing it a pre-authenticated kite object. Just-in-Time Authentication: Re-set the access_token on the original kite object immediately before the place_order call inside the place_trade function. Fresh Instance (Brute-Force): Created a brand new KiteConnect instance inside place_trade, authenticated it, and used it for the single API call. This also failed with the same error. Environment Cleaning: Cleared all __pycache__ directories to rule out stale code. Relevant Code Snippets
This is the place_trade function in agents.py with the latest attempted fix (just-in-time re-authentication), which still fails.
Python
# From agents.py async def place_trade(self, direction): symbol, qty = await self._get_trade_details(direction) # ... try: order_params = { ... } logging.info(f"Placing LIVE order -> {order_params}")
# This is the latest attempted fix logging.info("Re-authenticating original Kite session before placing order...") token_to_use = self.config['zerodha']['access_token'] logging.info(f"DIAGNOSTIC: Token being used for trade: {token_to_use}") self.kite.set_access_token(token_to_use)
# The API call is made in a separate thread order_id = await asyncio.to_thread(self.kite.place_order, **order_params) # ... except Exception as e: logging.error(f"Failed to place live order for {symbol}: {e}", exc_info=True) return None My Questions for the Community
Is there a known issue or limitation when using an access_token in a long-running asyncio application where the API call is delegated to a worker thread? Could the access_token be implicitly tied to more than just the api_key (e.g., the original requests.Session object, IP address, or user-agent) which gets lost when the call is made from a different thread context? Is there a session invalidation rule (e.g., if another login occurs on Web or Mobile) that could be causing this, and if so, what is the best practice for handling it in a bot that needs to run for an entire day? Any insight or guidance would be greatly appreciated, as I have exhausted all debugging paths within my application's logic.