{"record":{"id":"454c80115fbe0312","repo":"nautechsystems/nautilus_trader","slug":"height-must-be-positive-was-self-height","errorCode":null,"errorMessage":"height must be positive, was {self.height}","messagePattern":"height must be positive, was (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/nautilus_trader/analysis/config.py","lineNumber":316,"sourceCode":"        Whether to display NautilusTrader logo in the tearsheet.\n\n    \"\"\"\n\n    charts: list[TearsheetChart] = field(default_factory=_default_charts)\n    theme: str = \"plotly_white\"\n    layout: GridLayout | None = None\n    title: str = \"NautilusTrader Backtest Results\"\n    include_benchmark: bool = True\n    benchmark_name: str = \"Benchmark\"\n    height: int = 1500\n    show_logo: bool = True\n\n    def __post_init__(self) -> None:\n        \"\"\"\n        Validate the configuration.\n        \"\"\"\n        if self.height <= 0:\n            raise ValueError(f\"height must be positive, was {self.height}\")\n\n    @property\n    def chart_names(self) -> list[str]:\n        \"\"\"\n        The names of the configured charts, in order.\n        \"\"\"\n        return [c.name for c in self.charts]\n","sourceCodeStart":298,"sourceCodeEnd":324,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/python/nautilus_trader/analysis/config.py#L298-L324","documentation":"During Feather-to-Parquet conversion, ParquetDataCatalog::convert_feather_batches_to_parquet computes the (start_ts, end_ts) range from the batch's ts_init column via Self::ts_init_range (catalog.rs:4130). That helper fails when the batch has no ts_init column, the column is not UInt64, contains nulls, or the batch is empty; this error wraps that inner failure with the offending feather_path for context.","triggerScenarios":"Calling convert_stream_to_data (which calls convert_feather_batches_to_parquet) on a Feather file whose RecordBatch lacks a ts_init column, has ts_init typed as something other than UInt64Array, contains null values in ts_init, or is an empty/zero-row batch.","commonSituations":"Legacy or hand-written Feather files exported before the ts_init column convention existed; custom data written without NautilusTrader's standard timestamp columns; files produced by external ETL scripts that wrote i64 timestamps instead of UInt64; truncated/empty feather files left by a crashed conversion run.","solutions":["Inspect the Feather file's schema and ensure it contains a non-null UInt64 ts_init column (e.g. check batch.schema().index_of(\"ts_init\") and the column type) before converting.","If ts_init is missing, derive it from ts_event: use the use_ts_event_for_ts_init option in the stream conversion (which copies ts_event into ts_init), or rewrite the file adding the column.","If ts_init is null in some rows, fix the upstream write that produced nulls, or filter out those rows before conversion.","If the file is empty, delete or skip it; ts_init_range explicitly rejects empty batches.","Check the inner error message (appended after the wrapped context) to see which of the four underlying conditions actually fired."],"exampleFix":"// before: converting a feather batch lacking proper ts_init\nlet (start_ts, end_ts) = Self::ts_init_range(&batch)?;\n\n// after: guard the schema before conversion\nlet ts_init = batch.schema().column_with_name(\"ts_init\")\n    .filter(|(_, f)| f.data_type() == &DataType::UInt64)\n    .ok_or_else(|| anyhow::anyhow!(\"feather file must contain a UInt64 ts_init column\"))?\nassert!(batch.num_rows() > 0, \"skip empty feather files\");","handlingStrategy":"validation","validationCode":"let schema = batch.schema();\nlet ok = schema.column_with_name(\"ts_init\")\n    .filter(|(_, f)| f.data_type() == &DataType::UInt64)\n    .map(|(i, _)| batch.column(i).null_count() == 0)\n    .unwrap_or(false);\nassert!(ok && batch.num_rows() > 0, \"batch must have non-null UInt64 ts_init and >0 rows\");","typeGuard":"fn has_valid_ts_init(batch: &RecordBatch) -> bool {\n    batch.schema().column_with_name(\"ts_init\")\n        .filter(|(_, f)| f.data_type() == &DataType::UInt64)\n        .map(|(i, _)| batch.column(i).null_count() == 0)\n        .unwrap_or(false)\n        && batch.num_rows() > 0\n}","tryCatchPattern":"match convert_stream_to_data(...).await {\n    Err(e) if e.to_string().contains(\"ts_init range\") => {\n        // inspect feather schema, repair or skip the file\n    }\n    r => r?,\n}","preventionTips":["Always write Feather files with NautilusTrader's writer so ts_event/ts_init UInt64 columns are present","Validate schema and null counts of legacy files before batch conversion","Skip or quarantine zero-row feather files before running conversion","Keep writer and reader arrow-rs versions aligned"],"tags":["parquet","arrow","data-conversion","schema","persistence"],"backgroundTag":"schema-validation-failed","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}