{"record":{"id":"3ea36a27b9644e5c","repo":"BoundaryML/baml","slug":"replace-search-argument-must-be-a-string-at","errorCode":null,"errorMessage":"replace() search argument must be a string at {:?}","messagePattern":"replace\\(\\) search argument must be a string at (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/baml-compiler/src/thir/interpret.rs","lineNumber":2980,"sourceCode":"            };\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            ))\n        }\n        \"replace\" => {\n            let BamlValueWithMeta::String(s, _) = receiver else {\n                bail!(\"replace() method only available on strings at {:?}\", meta.0);\n            };\n            if args.len() != 2 {\n                bail!(\"replace() method takes exactly 2 arguments at {:?}\", meta.0);\n            }\n            let BamlValueWithMeta::String(search, _) = &args[0] else {\n                bail!(\"replace() search argument must be a string at {:?}\", meta.0);\n            };\n            let BamlValueWithMeta::String(replacement, _) = &args[1] else {\n                bail!(\n                    \"replace() replacement argument must be a string at {:?}\",\n                    meta.0\n                );\n            };\n            // Replace first occurrence only (matching JavaScript behavior)\n            let result = s.replacen(search.as_str(), replacement.as_str(), 1);\n            Ok(BamlValueWithMeta::String(result, meta.clone()))\n        }\n        \"to_fixed\" => {\n            let value = match receiver {\n                BamlValueWithMeta::Float(v, _) => *v,\n                BamlValueWithMeta::Int(v, _) => *v as f64,\n                _ => bail!(\n                    \"to_fixed() method only available on floats and ints at {:?}\",\n                    meta.0","sourceCodeStart":2962,"sourceCodeEnd":2998,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/baml-compiler/src/thir/interpret.rs#L2962-L2998","documentation":"For the \"replace\" string method, the first argument (the search substring) must be a String value. The interpreter pattern-matches BamlValueWithMeta::String on args[0] and bails otherwise. Plain substring search only — no regex or non-string needles.","triggerScenarios":"Calling s.replace(nonString, replacement), e.g. replace(42, \"x\"), replace(someMap, \"x\"), or passing a null from an LLM field as the search term.","commonSituations":"Passing numbers (like IDs) directly as the search argument; a variable inferred as int/float being used where a string literal was expected.","solutions":["Wrap the search argument in a string (e.g. ToString(), or quote the literal)","Ensure the argument expression is statically typed/annotated as string","Convert numeric search terms to their string form before the call"],"exampleFix":"// before\nlet out = s.replace(id, \"REDACTED\");\n// after\nlet out = s.replace(id.ToString(), \"REDACTED\");","handlingStrategy":"type-guard","validationCode":"// arg0 must be a string: if (search is string) { s.replace(search, repl); }","typeGuard":"fn is_string(v: Value) -> bool { matches!(v, Value::String(_)) }","tryCatchPattern":"try { out = s.replace(search, repl); } catch (e) { log(e); }","preventionTips":["Quote search literals","Convert numeric search terms with ToString()","Validate LLM-sourced fields are strings before use"],"tags":["runtime","type-mismatch","arguments","strings"],"backgroundTag":"type-mismatch","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"}