{"record":{"id":"f60c3a9a704a43ec","repo":"BoundaryML/baml","slug":"substring-method-only-available-on-strings-at","errorCode":null,"errorMessage":"substring() method only available on strings at {:?}","messagePattern":"substring\\(\\) method only available on strings at (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/baml-compiler/src/thir/interpret.rs","lineNumber":2946,"sourceCode":"        \"split\" => {\n            let BamlValueWithMeta::String(s, _) = receiver else {\n                bail!(\"split() method only available on strings at {:?}\", meta.0);\n            };\n            if args.len() != 1 {\n                bail!(\"split() method takes exactly 1 argument at {:?}\", meta.0);\n            }\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());","sourceCodeStart":2928,"sourceCodeEnd":2964,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/baml-compiler/src/thir/interpret.rs#L2928-L2964","documentation":"The \"substring\" method is only defined for string receivers. When the interpreter dispatches \"substring\" it pattern-matches the receiver as BamlValueWithMeta::String and bails with this message for any other value type. It enforces that substring(start, end) operates on a string.","triggerScenarios":"Calling <non-string>.substring(0, 5) in a BAML expression — e.g. on an int, a list, a map, or a null value.","commonSituations":"Slicing a value assumed to be text but produced by extraction as a number/list; calling substring on an optional field that is null at runtime; refactors that changed a variable's type upstream.","solutions":["Confirm the receiver's actual type at the failing expression and convert it to a string before slicing.","Fix the upstream expression/annotation so the value is a string when substring is called.","Guard the call with a type check when the receiver type is dynamic or optional."],"exampleFix":"// before (n is an int)\nlet head = n.substring(0, 2);\n\n// after\nlet head = n.to_string().substring(0, 2);","handlingStrategy":"type-guard","validationCode":"// guard the receiver before substring\nif (v is string) {\n  return v.substring(0, 5);\n}","typeGuard":"fn is_string(v: BamlValue) -> bool { matches!(v, BamlValue::String(_)) }","tryCatchPattern":"match result {\n  Err(e) if e.to_string().contains(\"substring() method only available on strings\") => fallback_string,\n  other => other,\n}","preventionTips":["Convert numbers/lists to strings before slicing.","Null-check optional fields before string operations.","Keep extraction outputs string-typed when downstream code slices them."],"tags":["baml","type-mismatch","string-method","runtime"],"backgroundTag":"type-mismatch","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}