nautechsystems/nautilus_trader · error

API key must be provided or set in the 'TARDIS_API_KEY' envi

Error message

API key must be provided or set in the 'TARDIS_API_KEY' environment variable

What it means

The Tardis HTTP client requires an API key for authentication (Tardis API is key-gated). Credential::resolve checks the explicit `api_key` argument and then the TARDIS_API_KEY environment variable; if neither yields a credential, the client refuses to construct.

Source

Thrown at crates/adapters/tardis/src/http/client.rs:92

impl TardisHttpClient {
    /// Creates a new [`TardisHttpClient`] instance.
    ///
    /// # Errors
    ///
    /// Returns an error if no API key is provided (argument or `TARDIS_API_KEY` env var),
    /// or if the HTTP client cannot be built.
    pub fn new(
        api_key: Option<&str>,
        base_url: Option<&str>,
        timeout_secs: Option<u64>,
        normalize_symbols: bool,
        proxy_url: Option<String>,
    ) -> anyhow::Result<Self> {
        let credential = Credential::resolve(api_key.map(ToString::to_string));

        if credential.is_none() {
            anyhow::bail!(
                "API key must be provided or set in the 'TARDIS_API_KEY' environment variable"
            );
        }

        let base_url =
            base_url.map_or_else(|| TARDIS_HTTP_BASE_URL.to_string(), ToString::to_string);

        let mut headers = HashMap::new();
        headers.insert(USER_AGENT.to_string(), NAUTILUS_USER_AGENT.to_string());

        if let Some(ref cred) = credential {
            headers.insert(
                "Authorization".to_string(),
                format!("Bearer {}", cred.api_key()),
            );
        }

        let keyed_quotas = vec![(TARDIS_REST_RATE_KEY.to_string(), *TARDIS_REST_QUOTA)];

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Set the environment variable: export TARDIS_API_KEY="your-key"
  2. Pass the key explicitly to the constructor: api_key = Some("your-key")
  3. In CI/deployment, inject the secret into the environment (e.g. GitHub Actions secrets, docker -e)
  4. Check for typos in the env var name and that the process actually inherits it (printenv TARDIS_API_KEY)

Example fix

// before
let client = TardisHttpClient::new(None, None, None, None)?;  // no key anywhere
// after
let client = TardisHttpClient::new(Some("td-xxxx"), None, None, None)?;
// or: export TARDIS_API_KEY="td-xxxx" then TardisHttpClient::new(None, ...)
Defensive patterns

Strategy: validation

Validate before calling

fn ensure_tardis_key(api_key: Option<&str>) -> Result<(), String> {
    let resolved = api_key
        .map(str::trim)
        .filter(|k| !k.is_empty())
        .map(String::from)
        .or_else(|| std::env::var("TARDIS_API_KEY").ok());
    match resolved {
        Some(_) => Ok(()),
        None => Err("Set TARDIS_API_KEY or pass api_key".into()),
    }
}

Try / catch

let client = TardisHttpClient::new(api_key, None, None, None)
    .map_err(|e| {
        if e.to_string().contains("API key must be provided") {
            anyhow::anyhow!("TARDIS_API_KEY missing: export it or pass api_key explicitly")
        } else { e }
    })?;

Prevention

When it happens

Trigger: Calling the Tardis HTTP client constructor (new) with None/empty api_key while the TARDIS_API_KEY environment variable is unset in the process environment.

Common situations: Forgot to export TARDIS_API_KEY in the shell or container; key set in a different environment (IDE vs terminal vs systemd); key passed with surrounding whitespace or as an empty string; running in CI where the secret wasn't injected.

Understand the failure class

Background: "API key is required" / "API key not found" / "No API key was set": the missing-api-key error family across 16 libraries — this error's family across 16 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/10999fcbb3f8049e. Report an issue: GitHub.