nautechsystems/nautilus_trader · error
unsupported canonical run outcome
Error message
unsupported canonical run outcome
What it means
The canonical run document's `outcome` field is restricted to the closed set of strings "completed", "failed", "incomplete", or "stopped`. `validate_run` throws this error when `outcome` is any other string, a non-string value, or absent (though missing fields are normally caught earlier by validate_fields). It guarantees consumers can exhaustively match on run outcomes.
Source
Thrown at crates/backtest/src/result.rs:462
"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(())
}
fn validate_unsigned_decimal(value: &Value, field: &str, nullable: bool) -> anyhow::Result<()> {
if nullable && value.is_null() {
return Ok(());
}
let value = value
.as_str()
.ok_or_else(|| anyhow::anyhow!("canonical run field '{field}' must be a decimal string"))?;
anyhow::ensure!(
value == "0"View on GitHub (pinned to 18893faf8b)
Solutions
- Map your outcome to one of the supported values: completed, failed, incomplete, stopped
- Regenerate the result with the current library version so the canonical writer emits a valid outcome
- Update translation/import code to normalize outcome strings before validation
- Check the schema version of the input document against what this validator expects
Example fix
// before
{"run": {"outcome": "success", ...}}
// after
{"run": {"outcome": "completed", ...}} Defensive patterns
Strategy: validation
Validate before calling
const OUTCOMES: &[&str] = &["completed", "failed", "incomplete", "stopped"];
fn outcome_is_valid(run: &serde_json::Value) -> bool {
run.get("outcome")
.and_then(serde_json::Value::as_str)
.map_or(false, |o| OUTCOMES.contains(&o))
} Type guard
fn is_supported_outcome(v: &serde_json::Value) -> bool {
matches!(v.as_str(), Some("completed" | "failed" | "incomplete" | "stopped"))
} Try / catch
match validate_document(&doc) {
Err(e) if e.to_string().contains("canonical run outcome") => {
// normalize outcome string to the supported set and retry
}
other => other,
} Prevention
- Use an enum for outcome in producing code and serialize via the canonical writer
- Normalize foreign outcome vocabulary (success/ok) at import time
- Keep a single source of truth for the outcome enum
- Add a pre-validation step on imported result documents
When it happens
Trigger: Validating a canonical result where `run.outcome` is a value outside the allowed enum — e.g. "ok", "success", "aborted", an empty string, or a non-string such as null/number. Common when documents come from a different version or custom tooling that uses different outcome vocabulary.
Common situations: Custom backtest runners writing their own outcome strings; schema drift after the outcome enum was tightened in this version; translating results from another system (e.g. "success" vs "completed"); hand-edited fixtures.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 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 run configuration ID must be a string or null
- canonical trader ID must be a string
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/3eef2b79ba898dbe.
Report an issue: GitHub.