nautechsystems/nautilus_trader · error
Custom data type "{type_name}" is already registered for JSO
Error message
Custom data type "{type_name}" is already registered for JSON What it means
register_json_deserializer adds a JSON deserializer to the custom-data registry keyed by type name. The registry forbids duplicates, so registering the same type name twice bails with this error instead of silently overwriting the existing deserializer.
Source
Thrown at crates/model/src/data/registry.rs:75
json: DashMap::new(),
#[cfg(feature = "arrow")]
arrow: DashMap::new(),
})
}
/// Registers a JSON deserializer for the given custom data type name.
/// When `Data::deserialize` sees this type name, it will call this function.
///
/// # Errors
/// Returns an error if the type is already registered.
pub fn register_json_deserializer(
type_name: &str,
deserializer: JsonDeserializer,
) -> Result<(), anyhow::Error> {
let reg = registries();
match reg.json.entry(type_name.to_string()) {
Entry::Occupied(_) => {
anyhow::bail!("Custom data type \"{type_name}\" is already registered for JSON");
}
Entry::Vacant(v) => {
v.insert(deserializer);
Ok(())
}
}
}
/// Registers a JSON deserializer for the given custom data type name if not already registered.
/// If the type is already registered, returns `Ok(())` without overwriting (idempotent).
/// Use this where repeated registration can occur (e.g. module init).
///
/// # Errors
/// Does not return an error (idempotent insert into `DashMap`).
pub fn ensure_json_deserializer_registered(
type_name: &str,
deserializer: JsonDeserializer,
) -> Result<(), anyhow::Error> {View on GitHub (pinned to 18893faf8b)
Solutions
- Call registration only once, e.g. with a std::sync::Once / lazy static or an idempotent init guard.
- Check first (or catch this error) and treat 'already registered' as success in idempotent init paths.
- Use distinct type names if two genuinely different types collide.
Example fix
// before
register_custom_data_json("MyData", deser)?; // fails on second init
// after
static INIT: Once = Once::new();
INIT.call_once(|| register_custom_data_json("MyData", deser).unwrap()); Defensive patterns
Strategy: try-catch
Validate before calling
// Rust — check before registering // if registry already contains key, skip (expose a lookup or maintain your own Once)
Try / catch
// Rust
if let Err(e) = register_json_deserializer(type_name, deser) {
if e.to_string().contains("already registered") { Ok(()) } else { Err(e) } // idempotent
} else { Ok(()) } Prevention
- Initialize registries once per process using OnceLock or a module-level flag.
- In Python, put registration calls under `if not getattr(mod, '_registered', False)`.
- Keep registration in a dedicated init function called from a single entry point.
When it happens
Trigger: Calling register_json_deserializer (or register_custom_data_json) twice for the same type_name, e.g. on module re-import, repeated adapter initialization, or two crates registering the same logical type.
Common situations: Python modules reloaded in notebooks or tests invoking registration each run; a library and application both registering the same custom type; hot-reloading adapters.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- CustomData registry returned non-custom data
- Custom data type "{type_name}" is already registered for Arr
- Custom data type "{type_name}" is already registered for Pyt
- Rust extractor factory for "{type_name}" is already register
- No tearsheet chart registered under '{chart_name}'.{hint} Re
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/1599aa5c736324cb.
Report an issue: GitHub.