{"record":{"id":"ac3c27f29f89e483","repo":"nautechsystems/nautilus_trader","slug":"lighter-query-order-requires-credentials","errorCode":null,"errorMessage":"Lighter query_order requires credentials","messagePattern":"Lighter query_order requires credentials","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/lighter/src/execution.rs","lineNumber":4551,"sourceCode":"            Some(state) => {\n                log::debug!(\"Lighter query_account replaying cached AccountState\");\n                self.emitter.send_account_state(state);\n            }\n            None => {\n                log::warn!(\n                    \"Lighter query_account: no AccountState cached yet \\\n                     (account_all_assets stream has not pushed since connect)\",\n                );\n            }\n        }\n        Ok(())\n    }\n\n    fn query_order(&self, cmd: QueryOrder) -> anyhow::Result<()> {\n        let credential = self\n            .credential\n            .as_ref()\n            .ok_or_else(|| anyhow::anyhow!(\"Lighter query_order requires credentials\"))?\n            .clone();\n        let registry = Arc::clone(&self.registry);\n        let http_client = self.http_client.clone();\n        let emitter = self.emitter.clone();\n        let core_account_id = self.core.account_id;\n        let dispatch = self.dispatch.clone();\n        let clock = self.clock;\n\n        self.spawn_task(\"query_order\", async move {\n            let report = lookup_order_status_report(\n                &http_client,\n                &registry,\n                &credential,\n                core_account_id,\n                Some(cmd.instrument_id),\n                Some(&cmd.client_order_id),\n                cmd.venue_order_id.as_ref(),\n                &dispatch,","sourceCodeStart":4533,"sourceCodeEnd":4569,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/lighter/src/execution.rs#L4533-L4569","documentation":"query_order performs an authenticated HTTP query against the Lighter API to resolve an order, requiring the credential for signing/authenticating the request. A None credential produces this error. Unlike pure cache lookups, order query goes to the exchange and therefore needs credentials.","triggerScenarios":"Calling query_order on a credential-less Lighter execution client to resolve order status/exchange order id from the exchange.","commonSituations":"Adapter started without API keys but strategy code calls query_order for reconciliation; keys missing in CI/staging environments; config parsing silently dropping the credential.","solutions":["Configure credentials on the client before calling query_order","Use the cache-only lookup (order state already known) instead of an exchange query when credentials are unavailable","Verify the credential is loaded (log its presence, never its value) at startup"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if client.credential().is_none() {\n    // fall back to cache-only order state instead of exchange query\n    return cache.lookup_order(&cmd.client_order_id);\n}","typeGuard":"fn has_credential(c: &LighterExecutionClient) -> bool {\n    c.credential().is_some()\n}","tryCatchPattern":"match client.query_order(cmd) {\n    Err(e) if e.to_string().contains(\"requires credentials\") => {\n        // use cached order state or configure credentials\n    }\n    other => other?,\n}","preventionTips":["Prefer cache lookups when order state is already local and fresh","Load and verify credentials during adapter startup","Ensure config parsing cannot silently drop the credential field"],"tags":["rust","lighter","credentials","query","http"],"backgroundTag":"missing-credentials","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}