{"record":{"id":"62d2d158ca1734cb","repo":"astral-sh/ruff","slug":"argument-index-should-not-be-out-of-range","errorCode":null,"errorMessage":"argument index should not be out of range","messagePattern":"argument index should not be out of range","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/ty_python_semantic/src/types/call/bind.rs","lineNumber":9510,"sourceCode":"                if let Some(builder) = context.report_lint(&UNKNOWN_ARGUMENT, range) {\n                    let mut diag = builder.into_diagnostic(format_args!(\n                        \"Unpacked argument may contain keyword arguments that do not match any known parameter{}\",\n                        callable_description\n                            .map(|description| format!(\" of {description}\"))\n                            .unwrap_or_default()\n                    ));\n                    if let Some(compound_diag) = compound_diag {\n                        compound_diag.add_context(db, env, &mut diag);\n                    } else if let Some(spans) = callable_ty.function_spans(context.db()) {\n                        let mut sub = SubDiagnostic::new(\n                            SubDiagnosticSeverity::Info,\n                            format_args!(\"{callable_kind} signature here\"),\n                        );\n                        sub.annotate(Annotation::primary(spans.signature));\n                        diag.sub(sub);\n                    }\n                }\n            }\n\n            Self::PositionalOnlyParameterAsKwarg {\n                argument_index,\n                parameter,\n            } => {\n                let range = context.get_range(node, *argument_index);\n                if let Some(builder) =\n                    context.report_lint(&POSITIONAL_ONLY_PARAMETER_AS_KWARG, range)\n                {\n                    let mut diag = builder.into_diagnostic(format_args!(\n                        \"Positional-only parameter {parameter} passed as keyword argument{}\",\n                        callable_description\n                            .map(|description| format!(\" of {description}\"))\n                            .unwrap_or_default()\n                    ));\n                    if let Some(compound_diag) = compound_diag {\n                        compound_diag.add_context(db, env, &mut diag);\n                    } else if let Some(spans) = callable_ty.function_spans(context.db()) {","sourceCodeStart":9492,"sourceCodeEnd":9528,"githubUrl":"https://github.com/astral-sh/ruff/blob/15f3fe6b15a5f00172f34b0f542f8ea277f5a586/crates/ty_python_semantic/src/types/call/bind.rs#L9492-L9528","documentation":"When reporting a call-binding error, get_argument_node maps an argument index back to syntax: it takes the nth argument of a Call node in source order, or of a ClassDef's keyword arguments (with `metaclass` excluded). The expect fires when the index is past the arguments actually present in the node - the inference-side index and the AST have drifted apart.","triggerScenarios":"An argument_index derived from signature matching (counting parameters with no corresponding source argument, or class keyword filtering miscounting `__init_subclass__`/metaclass cases) used against a Call/ClassDef node with fewer source arguments; also stale nodes after edits.","commonSituations":"Diagnostics for calls with implicit arguments, *unpacking, class keyword arguments, or newly changed argument-index accounting between the matcher and the reporter.","solutions":["Capture the exact expression and the diagnostic being emitted, and file a ty issue: this is a diagnostic-to-AST mapping bug, not a wrong type result","As a contributor: use the Option from nth() and fall back to the whole-call (or class) span instead of expecting","Check the keyword-only counting path in the ClassDef arm (metaclass exclusion) against the matcher's index"],"exampleFix":"// before\nlet arg = call_node.arguments.iter_source_order().nth(argument_index).expect(\"argument index should not be out of range\");\n\n// after\nlet arg = call_node.arguments.iter_source_order().nth(argument_index); // Option; caller falls back to the call span","handlingStrategy":"validation","validationCode":"// Before mapping an index to a node, confirm the node has that many source arguments:\nlet count = match node {\n    ast::AnyNodeRef::ExprCall(call) => call.arguments.iter_source_order().count(),\n    ast::AnyNodeRef::StmtClassDef(class) => class.arguments.as_deref()\n        .map(|a| a.iter_source_order().filter_map(ArgOrKeyword::as_keyword).count())\n        .unwrap_or(0),\n    _ => 0,\n};\nif argument_index.map_or(true, |i| i < count) { /* safe to map */ }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat index-to-node mapping as fallible: use the Option from nth() and fall back to the enclosing expression's span","Keep argument-index accounting identical between the matcher and the reporter, including class keyword and metaclass exclusions","When adding diagnostics for new call shapes, test them against calls with fewer source arguments than parameters"],"tags":["rust","ty","diagnostics","call-arguments","index-out-of-bounds","panic"],"backgroundTag":"index-out-of-bounds","analyzedSha":"15f3fe6b15a5f00172f34b0f542f8ea277f5a586","analyzedAt":"2026-08-20T16:33:49.445Z","contentChangedAt":"2026-08-20T16:33:49.445Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}