{"record":{"id":"1cf8bebbd9894b4b","repo":"nautechsystems/nautilus_trader","slug":"unknown-fee-token-fee-token-with-non-zero-fee","errorCode":null,"errorMessage":"Unknown fee token '{fee_token}' with non-zero fee {fee_amount}","messagePattern":"Unknown fee token '(.+?)' with non-zero fee (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/hyperliquid/src/http/parse.rs","lineNumber":747,"sourceCode":"            );\n        }\n        return Ok(instrument.quote_currency());\n    }\n\n    if let Some(currency) = Currency::try_from_str(fee_token) {\n        return Ok(currency);\n    }\n\n    if fee_amount.is_zero() {\n        let fallback = instrument.quote_currency();\n        log::debug!(\n            \"Unregistered fee token '{fee_token}' on zero-fee fill for {}; using {fallback} as fallback\",\n            instrument.id(),\n        );\n        return Ok(fallback);\n    }\n\n    anyhow::bail!(\"Unknown fee token '{fee_token}' with non-zero fee {fee_amount}\")\n}\n\nfn is_outcome_side_token(symbol: &str) -> bool {\n    let Some(rest) = symbol.strip_prefix('+') else {\n        return false;\n    };\n    !rest.is_empty() && rest.bytes().all(|b| b.is_ascii_digit())\n}\n\n// Hyperliquid documents a venue-wide minimum order notional: $10 for perps,\n// and 10 quote_token for spot.\n// https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/error-responses\nconst HYPERLIQUID_MIN_ORDER_NOTIONAL: Decimal = Decimal::TEN;\n\n/// Converts a single Hyperliquid instrument definition into a Nautilus `InstrumentAny`.\n///\n/// Returns `None` if the conversion fails (e.g., unsupported market type).\n///","sourceCodeStart":729,"sourceCodeEnd":765,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/hyperliquid/src/http/parse.rs#L729-L765","documentation":"resolve_fee_currency maps a fill's fee token to a known currency. If the token is neither registered, nor a side token, nor resolvable via the instrument, and the fee is non-zero (so it cannot be silently ignored with a quote fallback), the parser bails with this error naming the unknown token and amount.","triggerScenarios":"parse_fill_report receiving a fill whose fee token string is not a known currency for the instrument and carries a non-zero fee — e.g. a new/unregistered token appears as fee denomination in the venue fill response.","commonSituations":"New tokens listed on Hyperliquid before the adapter's currency registry includes them; fee reported in an unexpected asset (e.g. USDT instead of USDC); adapter currency registry not initialized with all venue tokens.","solutions":["Register the unknown token as a Currency in the adapter's currency registry so it can be resolved.","Update the Hyperliquid adapter to a version that knows the new fee token.","Inspect the raw fill payload to confirm the venue's fee token; if it is wrong for this market, report the venue/API inconsistency.","If the fee were zero this would fall back to the quote currency — for non-zero fees the exact currency must be resolvable, so ensure correct instrument/currency initialization at connect time."],"exampleFix":"// before\n// fill arrives with fee token \"XYZ\" not in registry -> Unknown fee token 'XYZ' with non-zero fee 1.5\n// after\nif let Some(cur) = currency_registry.get(\"XYZ\") { /* fee resolvable */ } else {\n    currency_registry.register(Currency::from(\"XYZ\", 8)); // register new venue token\n}","handlingStrategy":"try-catch","validationCode":"fn fee_token_known(token: &str, registry: &CurrencyRegistry) -> bool {\n    registry.get(token).is_some()\n}","typeGuard":null,"tryCatchPattern":"match resolve_fee_currency(fee_token, fee_amount, instrument) {\n    Ok(cur) => apply_fee(cur, fee_amount),\n    Err(e) if e.to_string().contains(\"Unknown fee token\") => {\n        log::warn!(\"unregistered fee token; register it and re-process fill: {e}\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Register all venue currencies in the adapter registry at startup","Keep the adapter updated when new tokens list on Hyperliquid","Log raw fills when a new fee token appears so it can be registered"],"tags":["rust","hyperliquid","fees","unknown-currency","parse"],"backgroundTag":"record-not-found","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"}