{"record":{"id":"9e1ce5f17683f305","repo":"BoundaryML/baml","slug":"substring-method-takes-exactly-2-arguments-at","errorCode":null,"errorMessage":"substring() method takes exactly 2 arguments at {:?}","messagePattern":"substring\\(\\) method takes exactly 2 arguments at (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/baml-compiler/src/thir/interpret.rs","lineNumber":2952,"sourceCode":"            }\n            let BamlValueWithMeta::String(delimiter, _) = &args[0] else {\n                bail!(\"split() argument must be a string at {:?}\", meta.0);\n            };\n            let parts: Vec<BamlValueWithMeta<ExprMetadata>> = s\n                .split(delimiter.as_str())\n                .map(|part| BamlValueWithMeta::String(part.to_string(), meta.clone()))\n                .collect();\n            Ok(BamlValueWithMeta::List(parts, meta.clone()))\n        }\n        \"substring\" => {\n            let BamlValueWithMeta::String(s, _) = receiver else {\n                bail!(\n                    \"substring() method only available on strings at {:?}\",\n                    meta.0\n                );\n            };\n            if args.len() != 2 {\n                bail!(\n                    \"substring() method takes exactly 2 arguments at {:?}\",\n                    meta.0\n                );\n            }\n            let BamlValueWithMeta::Int(start, _) = &args[0] else {\n                bail!(\"substring() start argument must be an int at {:?}\", meta.0);\n            };\n            let BamlValueWithMeta::Int(end, _) = &args[1] else {\n                bail!(\"substring() end argument must be an int at {:?}\", meta.0);\n            };\n\n            let start = (*start as usize).min(s.len());\n            let end = (*end as usize).min(s.len()).max(start);\n\n            Ok(BamlValueWithMeta::String(\n                s[start..end].to_string(),\n                meta.clone(),\n            ))","sourceCodeStart":2934,"sourceCodeEnd":2970,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/baml-compiler/src/thir/interpret.rs#L2934-L2970","documentation":"The substring method has a fixed arity of two arguments (start and end indices). If a call passes any other number of arguments, the interpreter bails with this message. The library enforces the exact signature substring(start, end).","triggerScenarios":"Calling s.substring(0) with one argument (expecting a Python-like end-omitted slice), or s.substring(0, 5, 2) with three arguments, in BAML expression code.","commonSituations":"Porting Python/JS slicing habits (`s[0:]` or `substring(0)`) into BAML; passing an optional step argument; forgetting the end index.","solutions":["Supply both arguments: s.substring(start, end).","To slice to the end of the string, pass the string's length (or a large number — end is clamped with .min(s.len())) as the second argument.","Remove any extra arguments at the failing call site."],"exampleFix":"// before\nlet tail = s.substring(2);\n\n// after\nlet tail = s.substring(2, s.len());","handlingStrategy":"validation","validationCode":"// substring takes exactly 2 int arguments (start, end)\nlet args_ok = args.len() == 2;","typeGuard":null,"tryCatchPattern":"match result {\n  Err(e) if e.to_string().contains(\"takes exactly 2 arguments\") => log_missing_arg(\"substring\"),\n  other => other,\n}","preventionTips":["BAML substring always requires both start and end — unlike JS's substring(start) or Python slices.","Pass s.len() (or any large int; end is clamped) to slice to the end.","Search for substring( call sites with fewer than two arguments after refactors."],"tags":["baml","argument-count","string-method","arity"],"backgroundTag":"missing-required-argument","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}