{"record":{"id":"40bfe9b9913f637e","repo":"nushell/nushell","slug":"already-checked-that-is-a-series","errorCode":null,"errorMessage":"Already checked that is a series","messagePattern":"Already checked that is a series","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/nu_plugin_polars/src/dataframe/values/nu_dataframe/operations.rs","lineNumber":37,"sourceCode":"impl NuDataFrame {\n    pub fn compute_with_value(\n        &self,\n        plugin: &PolarsPlugin,\n        lhs_span: Span,\n        operator: Operator,\n        op_span: Span,\n        right: &Value,\n    ) -> Result<NuDataFrame, ShellError> {\n        let rhs_span = right.span();\n        match right {\n            Value::Custom { .. } => {\n                let rhs = NuDataFrame::try_from_value_coerce(plugin, right, rhs_span)?;\n\n                match (self.is_series(), rhs.is_series()) {\n                    (true, true) => {\n                        let lhs = &self\n                            .as_series(lhs_span)\n                            .expect(\"Already checked that is a series\");\n                        let rhs = &rhs\n                            .as_series(rhs_span)\n                            .expect(\"Already checked that is a series\");\n\n                        if lhs.dtype() != rhs.dtype() {\n                            return Err(ShellError::IncompatibleParameters {\n                                left_message: format!(\"datatype {}\", lhs.dtype()),\n                                left_span: lhs_span,\n                                right_message: format!(\"datatype {}\", lhs.dtype()),\n                                right_span: rhs_span,\n                            });\n                        }\n\n                        if lhs.len() != rhs.len() {\n                            return Err(ShellError::IncompatibleParameters {\n                                left_message: format!(\"len {}\", lhs.len()),\n                                left_span: lhs_span,\n                                right_message: format!(\"len {}\", rhs.len()),","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/nushell/nushell/blob/8e03210652f3c48c4521cec982d96e4cb6c67181/crates/nu_plugin_polars/src/dataframe/values/nu_dataframe/operations.rs#L19-L55","documentation":"Panic in NuDataFrame::computed_binary_op (operations.rs): in the (true, true) arm after matching (self.is_series(), rhs.is_series()), the lhs is converted with as_series(lhs_span).expect('Already checked that is a series'). Since the match arm only runs when both frames have width 1, as_series cannot take its error branch and first() cannot be None — the expect documents the match/lookup agreement and is effectively unreachable.","triggerScenarios":"Divergence between the is_series() predicate and as_series()'s internal check (e.g. someone changes one without the other), or concurrent mutation of either dataframe between the match and the conversion.","commonSituations":"Only relevant to nu_plugin_polars maintainers/refactors; users performing arithmetic between single-column dataframes get real ShellErrors (IncompatibleParameters, etc.) long before this can matter.","solutions":["Keep is_series() and as_series()'s width check derived from the same predicate when refactoring","Avoid sharing/mutating NuDataFrame values across threads during operations","Consider replacing the expects in the (true, true) arm with error returns to future-proof"],"exampleFix":"// before\nlet lhs = &self.as_series(lhs_span).expect(\"Already checked that is a series\");\n\n// after: reuse the already-checked width directly\nlet lhs = self.df.get_columns()[0].as_materialized_series();","handlingStrategy":"validation","validationCode":"// ensure both operands are single-column before the operation\nif !(lhs.is_series() && rhs.is_series()) {\n    return Err(ShellError::IncompatibleParametersSingle { msg: \"operands must be single-column dataframes\".into(), span: lhs_span });\n}","typeGuard":"fn both_series(l: &NuDataFrame, r: &NuDataFrame) -> bool {\n    l.is_series() && r.is_series()\n}","tryCatchPattern":null,"preventionTips":["Select a single column from each side before dataframe arithmetic","Avoid mutating the operands concurrently during the operation","Report a hit upstream — user pipelines cannot legitimately trigger it"],"tags":["nushell","polars","rust","panic","expect","dataframe","binary-op"],"backgroundTag":"check-then-use-invariant-panic","analyzedSha":"8e03210652f3c48c4521cec982d96e4cb6c67181","analyzedAt":"2026-08-17T16:24:07.527Z","contentChangedAt":"2026-08-17T16:24:07.527Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}