{"record":{"id":"3e2c5ed29d7105bd","repo":"facebook/flow","slug":"type-size-limit-exceeded","errorCode":null,"errorMessage":"Type size limit exceeded","messagePattern":"Type size limit exceeded","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"rust_port/crates/flow_typing_ty_normalizer/src/normalizer.rs","lineNumber":355,"sourceCode":"            rec_tvar_ids: BTreeSet::new(),\n            rec_eval_ids: BTreeSet::new(),\n            found_computed_type: false,\n            remaining_type_size: None,\n        }\n    }\n\n    pub fn found_computed_type(&self) -> bool {\n        self.found_computed_type\n    }\n\n    fn reset_type_size_budget(&mut self, max_type_size: Option<usize>) {\n        self.remaining_type_size = max_type_size;\n    }\n\n    fn consume_type_node(&mut self) -> Result<(), Error> {\n        match self.remaining_type_size {\n            None => Ok(()),\n            Some(0) => Err(Error::new(\n                ErrorKind::TypeSizeLimit,\n                String::from(\"Type size limit exceeded\"),\n            )),\n            Some(remaining) => {\n                self.remaining_type_size = Some(remaining - 1);\n                Ok(())\n            }\n        }\n    }\n}\n\n// Each run of the monad gets assigned its own id.\nthread_local! {\n    static RUN_ID: Cell<i32> = const { Cell::new(0) };\n}\n\n// Wrapper around 'run' that assigns a distinct id to every run of the monad.\nfn run<T, F>(state: &mut State, f: F) -> Result<T, Error>","sourceCodeStart":337,"sourceCodeEnd":373,"githubUrl":"https://github.com/facebook/flow/blob/21c11b2eada01107bc3a459b0e99a7e56a502ddc/rust_port/crates/flow_typing_ty_normalizer/src/normalizer.rs#L337-L373","documentation":"This error is thrown by the type normalizer when the normalization of a type visits more type nodes than the configured budget (max_type_size) allows. State::consume_type_node decrements a counter for every type node visited; when the counter is already 0, it fails with ErrorKind::TypeSizeLimit and message \"Type size limit exceeded\". The limit exists to guard against pathologically large or recursive types blowing up normalization time/memory.","triggerScenarios":"Normalizing a type whose AST has more nodes than the remaining budget: a State with remaining_type_size = Some(n) where consuming more than n nodes is required. This happens when reset_type_size_budget was called with a small max, or the type being normalized is genuinely huge/deeply recursive.","commonSituations":"Very large generated or deeply nested types (e.g. huge trait objects, long tuple/union chains), mutually recursive type aliases expanded during normalization, or a max type size configured too low for the codebase being type-checked.","solutions":["Increase the configured maximum type size passed to reset_type_size_budget (raise the budget for the analysis run).","Check the type being normalized for accidental blowup (recursive alias expansion, excessively large unions/tuples) and simplify it in the source program.","If the limit is intentional, treat this error as a signal to bail out of normalizing that type and fall back to a normalized-type approximation or report a user-facing type-too-complex diagnostic.","Verify the budget is not being reset/decremented across unrelated types, which would unfairly deplete it for later types."],"exampleFix":"// before\nstate.reset_type_size_budget(Some(1024));\n// after\nstate.reset_type_size_budget(Some(4096));","handlingStrategy":"try-catch","validationCode":"// estimate node count before normalizing and skip if over budget\nfn within_budget(ty: &Ty, budget: usize) -> bool {\n    ty.node_count() <= budget\n}","typeGuard":"fn is_type_size_limit(e: &Error) -> bool {\n    e.kind() == ErrorKind::TypeSizeLimit\n}","tryCatchPattern":"match state.normalize(ty) {\n    Ok(n) => n,\n    Err(e) if e.kind() == ErrorKind::TypeSizeLimit => {\n        // fall back: use un-normalized type or emit \"type too complex\" diagnostic\n        fallback_representation(ty)\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Set the type-size budget generously relative to the largest types in your codebase.","Measure/estimate type node counts offline and pick a budget with headroom.","Simplify or cap recursive type aliases and huge unions at the language level.","Handle TypeSizeLimit explicitly so one oversized type does not abort the whole analysis."],"tags":["rust","type-checker","resource-limit","recursion"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"21c11b2eada01107bc3a459b0e99a7e56a502ddc","analyzedAt":"2026-09-16T21:29:15.959Z","contentChangedAt":"2026-09-16T21:29:15.959Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}