BoundaryML/baml · error

feedback field "{key}" must be a string

Error message

feedback field "{key}" must be a string

What it means

In `baml feedback`, if a --json payload supplies "title" or "description" with a non-string JSON value (number, bool, object, null), the command errors rather than silently dropping it — the local record and PostHog preview previously dropped such values via as_str.

Source

Thrown at baml_language/crates/baml_cli/src/feedback_command.rs:403

            .map(String::as_str)
            .filter(|k| !matches!(*k, "title" | "description"))
            .collect();
        if !unknown.is_empty() {
            return Err(anyhow::anyhow!(
                "unknown feedback field(s) {}; only \"title\" and \
                 \"description\" are sent (attach files with --files)",
                unknown.join(", ")
            ));
        }

        // Validate types, not just names: a non-string field would ship to
        // PostHog while the preview and the local record (which read via
        // `as_str`) silently dropped it.
        for key in ["title", "description"] {
            if let Some(value) = obj.get(key)
                && !value.is_string()
            {
                return Err(anyhow::anyhow!("feedback field \"{key}\" must be a string"));
            }
        }

        let title = obj.get("title").and_then(Value::as_str).unwrap_or("");
        if title.trim().is_empty() {
            return Err(anyhow::anyhow!(
                "feedback needs a title; pass --title \"...\" or a JSON payload \
                 with a \"title\" field"
            ));
        }
        Ok(from_json)
    }

    /// Shows exactly what a report contains and how it is attributed.
    fn print_preview(&self, payload: &Value, identified: bool, email: Option<&str>) {
        if identified {
            println!(
                "reporting to Boundary as {}:",

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Quote the value so it is a JSON string: --json '{"title":"123"}'.
  2. Use null by omitting the field entirely rather than passing non-string values.
  3. Validate the payload with jq before passing it (jq -e '.title | type == "string"').

Example fix

// before
baml feedback --json '{"title":123}'
// after
baml feedback --json '{"title":"123"}'
Defensive patterns

Strategy: type-guard

Validate before calling

// ensure fields are strings before invoking
const p = JSON.parse(payload);
if (p.title !== undefined && typeof p.title !== 'string') throw new Error('title must be a string');
if (p.description !== undefined && typeof p.description !== 'string') throw new Error('description must be a string');

Type guard

const isStr = (v) => typeof v === 'string';
const validFeedback = (p) => ['title','description'].every(k => p[k] === undefined || isStr(p[k]));

Try / catch

try {
  run(`baml feedback --json '${payload}'`);
} catch (e) {
  if (String(e).includes('must be a string')) {
    const p = JSON.parse(payload);
    ['title','description'].forEach(k => { if (p[k] !== undefined) p[k] = String(p[k]); });
    run(`baml feedback --json '${JSON.stringify(p)}'`);
  }
}

Prevention

When it happens

Trigger: `baml feedback --json '{"title":123}'` or `--json '{"description":{"text":"x"}}'` — obj.get(key) exists but !value.is_string() for title or description.

Common situations: Building JSON payloads programmatically where numbers/booleans slip in; quoting mistakes in shell producing unquoted values; copying payloads that use null for empty fields.

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/12553ebddcbf96e9. Report an issue: GitHub.