nautechsystems/nautilus_trader · error
canonical run configuration ID must be a string or null
Error message
canonical run configuration ID must be a string or null
What it means
This error comes from `validate_run` in the backtest result module, which enforces the schema of the canonical (serialized) backtest result document. The `run_config_id` field of the `run` object must be either a JSON string or JSON null — anything else (number, boolean, missing-then-checked, array, object) is rejected. It exists so downstream consumers of the canonical document can rely on a stable, typed identifier for the run configuration.
Source
Thrown at crates/backtest/src/result.rs:452
"total_positions",
"trader_id",
],
"canonical result run",
)?;
for key in [
"iterations",
"total_events",
"total_orders",
"total_positions",
] {
validate_unsigned_decimal(object.get(key).expect("validated field"), key, false)?;
}
for key in ["backtest_start_ns", "backtest_end_ns"] {
validate_unsigned_decimal(object.get(key).expect("validated field"), key, true)?;
}
anyhow::ensure!(
object
.get("run_config_id")
.is_some_and(|value| value.is_null() || value.is_string()),
"canonical run configuration ID must be a string or null"
);
anyhow::ensure!(
object.get("trader_id").is_some_and(Value::is_string),
"canonical trader ID must be a string"
);
anyhow::ensure!(
matches!(
object.get("outcome").and_then(Value::as_str),
Some("completed" | "failed" | "incomplete" | "stopped")
),
"unsupported canonical run outcome"
);
Ok(())
}View on GitHub (pinned to 18893faf8b)
Solutions
- Ensure run_config_id is serialized as a string (or explicit null when no config ID exists)
- Re-generate the canonical result document with the current version of the library instead of reusing old artifacts
- Validate the JSON before passing it to validate_document and coerce non-string IDs to strings with String(value)
- Check that no post-processing step (jq, Python script) rewrote the field type
Example fix
// before
{"run": {"run_config_id": 12345, ...}}
// after
{"run": {"run_config_id": "12345", ...}} Defensive patterns
Strategy: validation
Validate before calling
fn run_config_id_is_valid(run: &serde_json::Value) -> bool {
run.get("run_config_id")
.is_some_and(|v| v.is_null() || v.is_string())
} Type guard
fn is_string_or_null(v: &serde_json::Value) -> bool {
v.is_null() || v.is_string()
} Try / catch
match validate_document(&doc) {
Err(e) if e.to_string().contains("run configuration ID") => {
// coerce run.run_config_id to string or null and retry
}
other => other,
} Prevention
- Always serialize run_config_id as a string or explicit null
- Use the library's canonical writer rather than hand-building result JSON
- Pin and check the result document schema version before validating
- Avoid numeric coercion of IDs in post-processing scripts
When it happens
Trigger: Calling `validate_document` on a canonical result JSON whose `run.run_config_id` is a non-string, non-null JSON value (e.g. an integer, an object, or an array). This happens when the document was produced by an older/other serializer or hand-edited rather than emitted by this library's canonical writer.
Common situations: Migrating results produced by a previous schema version where run_config_id was encoded as a number; hand-crafting or post-processing result JSON with a script that coerces the ID to a number; loading fixture files from a different codebase version.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- canonical backtest result must be a JSON object
- canonical result field '{key}' must be an array
- canonical result summary must be an object
- canonical trader ID must be a string
- canonical result statistics must be an object
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/41efbcfee454627f.
Report an issue: GitHub.