BoundaryML/baml · error

toUpperCase() method only available on strings at

Error message

toUpperCase() method only available on strings at {:?}

What it means

The BAML expression interpreter only allows calling toUpperCase() on a value that is already a string. At runtime the receiver expression evaluated to a non-string type (int, float, bool, null, map, array, etc.), so evaluate_method_call bails before performing the uppercase conversion. This mirrors JavaScript's 'toUpperCase is not a function' TypeError but surfaces at interpretation time.

Solutions

  1. Check the type of the receiver value and coerce it to a string before calling toUpperCase(), e.g. wrap it in string interpolation or use the appropriate string conversion function.
  2. Fix the upstream field/variable declaration so the value is declared (and produced) as a string type.
  3. If the value may be null or another type, branch on its type before calling the method.
  4. Inspect the span reported in the error message ({:?} meta span) to locate the exact receiver expression and correct it.

Example fix

// before
let upper = user.age.toUpperCase();
// after
let upper = "{{ user.age }}".toUpperCase();  // or declare age as string
Defensive patterns

Strategy: type-guard

Validate before calling

// before evaluating the expression
if (typeof value !== 'string') {
  throw new Error('toUpperCase() receiver must be a string, got: ' + typeof value);
}

Type guard

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

Try / catch

// wrap BAML function invocation
try {
  const res = await b.Function(args);
} catch (e) {
  if (String(e.message).includes('toUpperCase() method only available on strings')) {
    // coerce the offending field to string and retry once
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling `someValue.toUpperCase()` in a BAML expression block or string template where `someValue` is not a string — e.g. an int field, a bool, null, a map/array value, or the result of a function/prompt that returns a non-string type.

Common situations: Devs assume a field from a client-provided map or JSON input is a string when it is actually a number or bool; a function's return type changed from string to another type in a newer version of the BAML schema; optional/null values flow into a method call without a null check.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

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

                    meta.0
                ),
            }
        }
        "toLowerCase" => {
            let BamlValueWithMeta::String(s, _) = receiver else {
                bail!(
                    "toLowerCase() method only available on strings at {:?}",
                    meta.0
                );
            };
            if !args.is_empty() {
                bail!("toLowerCase() method takes no arguments at {:?}", meta.0);
            }
            Ok(BamlValueWithMeta::String(s.to_lowercase(), meta.clone()))
        }
        "toUpperCase" => {
            let BamlValueWithMeta::String(s, _) = receiver else {
                bail!(
                    "toUpperCase() method only available on strings at {:?}",
                    meta.0
                );
            };
            if !args.is_empty() {
                bail!("toUpperCase() method takes no arguments at {:?}", meta.0);
            }
            Ok(BamlValueWithMeta::String(s.to_uppercase(), meta.clone()))
        }
        "trim" => {
            let BamlValueWithMeta::String(s, _) = receiver else {
                bail!("trim() method only available on strings at {:?}", meta.0);
            };
            if !args.is_empty() {
                bail!("trim() method takes no arguments at {:?}", meta.0);
            }
            Ok(BamlValueWithMeta::String(
                s.trim().to_string(),

View on GitHub (pinned to bd85ce9dee)