{"record":{"id":"c11e019cd6a562e8","repo":"gleam-lang/gleam","slug":"wrong-number-of-subjects","errorCode":null,"errorMessage":"wrong number of subjects","messagePattern":"wrong number of subjects","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler-core/src/exhaustiveness.rs","lineNumber":3664,"sourceCode":"    /// If you don't have a clause and just have a simple `TypedPattern` you want\n    /// to generate a decision tree for you can use `add_pattern`.\n    ///\n    pub fn add_clause(&mut self, branch: &TypedClause) {\n        let all_patterns =\n            std::iter::once(&branch.pattern).chain(branch.alternative_patterns.iter());\n\n        for (alternative_index, patterns) in all_patterns.enumerate() {\n            let mut checks = Vec::with_capacity(patterns.len());\n\n            // We're doing the zipping ourselves instead of using iters.zip as the\n            // borrow checker would complain and the only workaround would be to\n            // allocate an entire new vector each time.\n            for i in 0..patterns.len() {\n                let pattern = self.register(patterns.get(i).expect(\"pattern index\"));\n                let var = self\n                    .subject_variables\n                    .get(i)\n                    .expect(\"wrong number of subjects\");\n                checks.push(var.is(pattern));\n            }\n\n            let has_guard = branch.guard.is_some();\n            let branch = Branch::new(self.number_of_clauses, alternative_index, checks, has_guard);\n            self.branches.push(branch);\n        }\n\n        self.number_of_clauses += 1;\n    }\n\n    /// Add a single pattern as a branch to be compiled.\n    ///\n    /// This is useful in case one wants to check exhaustiveness of a single\n    /// pattern without having a fully fledged `TypedClause` to pass to the `add_clause`\n    /// method. For example, in `let` destructurings.\n    ///\n    pub fn add_pattern(&mut self, pattern: &TypedPattern) {","sourceCodeStart":3646,"sourceCodeEnd":3682,"githubUrl":"https://github.com/gleam-lang/gleam/blob/49f8762da595eb3c8f576656a4200a142ca188c9/compiler-core/src/exhaustiveness.rs#L3646-L3682","documentation":"This panic comes from an `.expect(\"wrong number of subjects\")` inside the exhaustiveness (pattern-matching) compiler of the Gleam compiler core. When compiling a `case` expression's branches, each pattern list is zipped against the pre-registered subject variables; the length mismatch means a branch had more patterns than there were case subjects, which the typechecker should have rejected earlier. It is an internal invariant assertion, not a user-facing error.","triggerScenarios":"Calling `Compiler::compile_body` (or the clause-registration path) with a `patterns` iterator/Vec longer than `subject_variables` — e.g. an earlier AST pass failed to keep pattern count equal to the number of case subjects for a multi-subject case clause.","commonSituations":"Hitting this while hacking on the Gleam compiler: adding a new pattern desugaring that duplicates patterns, miscounting subjects in a rewrite pass, or fuzzing the frontend with malformed case expressions that bypass the typechecker's arity check.","solutions":["Check the number of patterns in each clause matches the number of case subjects before registration; the parser/typechecker should report 'case clause has too many patterns' instead","Verify the code that builds `subject_variables` pushes one variable per subject (look at where `Compiler::new` is called)","Run with a debug build to get the full panic backtrace and identify which pass produced the oversized pattern vector","If you are a library user (not compiler dev), this is a compiler bug — file an issue with the code that triggers it"],"exampleFix":"// before\nlet var = self.subject_variables.get(i).expect(\"wrong number of subjects\");\n// after\nlet var = self.subject_variables.get(i).unwrap_or_else(|| {\n    panic!(\"clause has {} patterns but {} subjects were registered\", patterns.len(), self.subject_variables.len())\n});","handlingStrategy":"validation","validationCode":"if patterns.len() != subjects.len() {\n    return Err(Error::CaseClauseArityMismatch { patterns: patterns.len(), subjects: subjects.len() });\n}","typeGuard":"fn clause_matches_subjects(patterns: &[TypedPattern], subjects: &[Variable]) -> bool {\n    patterns.len() == subjects.len()\n}","tryCatchPattern":null,"preventionTips":["Validate pattern arity per clause during typechecking before exhaustiveness compilation","Add a debug_assert_eq!(patterns.len(), self.subject_variables.len()) before the loop","Fuzz the frontend with multi-subject case expressions","Keep a unit test per AST pass that constructs case expressions"],"tags":["rust","compiler","pattern-matching","panic"],"backgroundTag":"internal-invariant-violation","analyzedSha":"49f8762da595eb3c8f576656a4200a142ca188c9","analyzedAt":"2026-09-14T11:14:59.388Z","contentChangedAt":"2026-09-14T11:14:59.388Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}