BoundaryML/baml · error

startsWith() argument must be a string at

Error message

startsWith() argument must be a string at {:?}

What it means

The argument to startsWith() must be a string; a non-string prefix (int, bool, null, etc.) makes evaluate_method_call bail. The check is implemented with Rust's str::starts_with, which requires a string prefix.

Solutions

  1. Convert the argument to a string before passing it: `s.startsWith("{{ prefix }}")`.
  2. Fix the prefix variable's declaration so it is a string type.
  3. Guard with a type/null check when the prefix may not be a string.
  4. Use the error span to locate the argument expression and correct it.

Example fix

// before
let isBeta = build.startsWith(majorVersion);  // int
// after
let isBeta = build.startsWith("{{ majorVersion }}");
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof prefix !== 'string') {
  throw new Error('startsWith() argument must be a string, got: ' + typeof prefix);
}

Type guard

const isStr = (v) => typeof v === 'string';

Try / catch

try {
  const res = await b.Function(args);
} catch (e) {
  if (String(e.message).includes('startsWith() argument must be a string')) {
    // coerce the prefix with string interpolation and retry
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling `s.startsWith(x)` where `x` evaluates to a non-string — e.g. startsWith(version) with an int version number, or a null optional as the prefix.

Common situations: Checking a numeric prefix without quoting it; passing a field from JSON/map input assumed to be a string but typed as a number or bool; a null optional flowing in without a guard.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/fb68bbb01fdd5356. Report an issue: GitHub.

Appendix: source

Thrown at engine/baml-compiler/src/thir/interpret.rs:2903

                s.contains(search.as_str()),
                meta.clone(),
            ))
        }
        "startsWith" => {
            let BamlValueWithMeta::String(s, _) = receiver else {
                bail!(
                    "startsWith() method only available on strings at {:?}",
                    meta.0
                );
            };
            if args.len() != 1 {
                bail!(
                    "startsWith() method takes exactly 1 argument at {:?}",
                    meta.0
                );
            }
            let BamlValueWithMeta::String(prefix, _) = &args[0] else {
                bail!("startsWith() argument must be a string at {:?}", meta.0);
            };
            Ok(BamlValueWithMeta::Bool(
                s.starts_with(prefix.as_str()),
                meta.clone(),
            ))
        }
        "endsWith" => {
            let BamlValueWithMeta::String(s, _) = receiver else {
                bail!(
                    "endsWith() method only available on strings at {:?}",
                    meta.0
                );
            };
            if args.len() != 1 {
                bail!("endsWith() method takes exactly 1 argument at {:?}", meta.0);
            }
            let BamlValueWithMeta::String(suffix, _) = &args[0] else {
                bail!("endsWith() argument must be a string at {:?}", meta.0);

View on GitHub (pinned to bd85ce9dee)