nautechsystems/nautilus_trader · error
max_fee_per_contract must be greater than zero
Error message
max_fee_per_contract must be greater than zero
What it means
Raised by `DeriveDataClientConfig::validate` when `max_fee_per_contract` is present but is less than or equal to zero. The adapter requires a strictly positive per-contract fee cap so order requests never send a non-sensical fee bound.
Source
Thrown at crates/adapters/derive/src/config.rs:271
.as_ref()
.map(SecretString::expose_secret)
.is_some_and(|s| !s.trim().is_empty())
&& self.subaccount_id.is_some()
}
/// Validates execution configuration invariants.
///
/// # Errors
///
/// Returns an error when `max_fee_per_contract` is missing or not greater
/// than zero.
pub fn validate(&self) -> anyhow::Result<()> {
let Some(max_fee_per_contract) = self.max_fee_per_contract else {
anyhow::bail!("max_fee_per_contract is required");
};
if max_fee_per_contract <= Decimal::ZERO {
anyhow::bail!("max_fee_per_contract must be greater than zero");
}
Ok(())
}
/// Returns the REST API base URL, respecting environment and overrides.
#[must_use]
pub fn rest_url(&self) -> String {
self.base_url_rest
.clone()
.unwrap_or_else(|| urls::rest_url(self.environment).to_string())
}
/// Returns the WebSocket URL, respecting environment and overrides.
#[must_use]
pub fn ws_url(&self) -> String {
self.base_url_ws
.clone()
.unwrap_or_else(|| urls::ws_url(self.environment).to_string())View on GitHub (pinned to 18893faf8b)
Solutions
- Set `max_fee_per_contract` to a positive Decimal (e.g. 0.01) in the config.
- Verify the value parsed from the config file is positive and not 0 or negative.
- Validate the config early (validate()) to surface the problem before client creation.
Example fix
// before max_fee_per_contract: Some(Decimal::ZERO), // after max_fee_per_contract: Some(Decimal::new(1, 2)), // 0.01
Defensive patterns
Strategy: validation
Validate before calling
if let Some(fee) = config.max_fee_per_contract {
assert!(fee > Decimal::ZERO, "max_fee_per_contract must be > 0");
}
config.validate()?; Try / catch
if let Err(e) = config.validate() {
return Err(anyhow::context!(e, "fix DeriveDataClientConfig before starting"));
} Prevention
- Never use Decimal::ZERO as a placeholder for fee caps.
- Clamp parsed config values to a positive minimum.
- Run validate() at startup, not at first order.
When it happens
Trigger: Setting `max_fee_per_contract` to `0`, a negative `Decimal`, or `Decimal::ZERO` in the DeriveDataClientConfig before client construction (`new` calls `validate`).
Common situations: Using Decimal::ZERO as a placeholder/default value; parsing an unquoted numeric 0 from config; sign confusion when entering a fee value; templating configs with empty values.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- max_fee_per_contract is required
- missing trigger price type for Derive trigger order; Derive
- post-only Derive orders only support GTC time in force; rece
- Instrument {instrument_id} not found and `auto_load_missing_
- Derive request_instruments requires at least one configured
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/af3616f15de409df.
Report an issue: GitHub.