{"record":{"id":"fc67b9b5076f2045","repo":"nautechsystems/nautilus_trader","slug":"lighter-execution-client-requires-credentials-set","errorCode":null,"errorMessage":"Lighter execution client requires credentials; set private_key, account_index, and api_key_index in the config or use the deployment-specific credential environment variables","messagePattern":"Lighter execution client requires credentials; set private_key, account_index, and api_key_index in the config or use the deployment-specific credential environment variables","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/adapters/lighter/src/execution.rs","lineNumber":4044,"sourceCode":"        self.begin_session_shutdown();\n        Ok(())\n    }\n\n    fn dispose(&mut self) -> anyhow::Result<()> {\n        log::debug!(\"Disposing Lighter execution client {}\", self.core.client_id);\n        self.stop()\n    }\n\n    async fn connect(&mut self) -> anyhow::Result<()> {\n        if self.core.is_connected() && self.pending_tasks.is_open() {\n            return Ok(());\n        }\n\n        // Without credentials the engine would accept the connection and\n        // then deny every order per-submission. Fail before any WS/REST\n        // work so reconciliation and strategies never start.\n        if !self.has_credentials() {\n            anyhow::bail!(\n                \"Lighter execution client requires credentials; \\\n                 set private_key, account_index, and api_key_index in the config \\\n                 or use the deployment-specific credential environment variables\"\n            );\n        }\n\n        log::info!(\n            \"Connecting Lighter execution client {}\",\n            self.core.client_id\n        );\n\n        // Synchronous stop/reset can only initiate teardown. Complete it before\n        // publishing a replacement socket or sharing its connection epoch.\n        if !self.session_tasks_finished() || !self.pending_tasks.is_open() {\n            self.begin_session_shutdown();\n            self.finish_session_shutdown().await?;\n        }\n","sourceCodeStart":4026,"sourceCodeEnd":4062,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/lighter/src/execution.rs#L4026-L4062","documentation":"The Lighter execution client validates at startup (before any WS/REST work) that credentials are present: private_key, account_index, and api_key_index. Without them the engine would accept the connection but deny every order per-submission, so the client fails fast with this message instead of letting reconciliation and strategies start in a broken state.","triggerScenarios":"Constructing/starting the Lighter execution client with a config missing any of private_key, account_index, or api_key_index, and with no deployment-specific credential environment variables set (has_credentials() returns false).","commonSituations":"Empty or partial config files, env vars not exported in the deployment environment (containers, CI), typos in config keys, or secrets managed by a secret store that failed to inject.","solutions":["Set private_key, account_index, and api_key_index in the Lighter adapter config","Or set the deployment-specific credential environment variables the adapter reads","Verify the secret injection (env/file mount) actually ran in the deployment environment","Re-check config key spelling and that the correct config file/profile is loaded"],"exampleFix":"// before: incomplete config\n{\n  \"execution\": { \"adapter\": \"lighter\" }\n}\n// after\n{\n  \"execution\": {\n    \"adapter\": \"lighter\",\n    \"private_key\": \"0x...\",\n    \"account_index\": 1,\n    \"api_key_index\": 0\n  }\n}","handlingStrategy":"validation","validationCode":"// Rust: validate credentials before constructing the client\nfn validate_lighter_config(cfg: &LighterExecConfig) -> Result<(), String> {\n    if cfg.private_key.is_empty() || cfg.account_index.is_none() || cfg.api_key_index.is_none() {\n        return Err(\"lighter execution requires private_key, account_index, api_key_index\".into());\n    }\n    Ok(())\n}","typeGuard":"fn has_credentials(cfg: &LighterExecConfig) -> bool {\n    cfg.private_key.as_deref().map_or(false, |k| !k.is_empty())\n        && cfg.account_index.is_some()\n        && cfg.api_key_index.is_some()\n}","tryCatchPattern":"let client = match LighterExecutionClient::new(cfg) {\n    Err(e) if e.to_string().contains(\"requires credentials\") => {\n        eprintln!(\"set LIGHTER_PRIVATE_KEY / LIGHTER_ACCOUNT_INDEX / LIGHTER_API_KEY_INDEX\");\n        return Err(e);\n    }\n    r => r?,\n};","preventionTips":["Validate config completeness at deployment start, before engine startup","Inject credentials via env vars in containers and assert they are non-empty","Add a startup smoke test that constructs the client with the deployment config"],"tags":["config","credentials","startup","rust","missing-config"],"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"}