{"record":{"id":"12553ebddcbf96e9","repo":"BoundaryML/baml","slug":"feedback-field-key-must-be-a-string","errorCode":null,"errorMessage":"feedback field \"{key}\" must be a string","messagePattern":"feedback field \"(.+?)\" must be a string","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"baml_language/crates/baml_cli/src/feedback_command.rs","lineNumber":403,"sourceCode":"            .map(String::as_str)\n            .filter(|k| !matches!(*k, \"title\" | \"description\"))\n            .collect();\n        if !unknown.is_empty() {\n            return Err(anyhow::anyhow!(\n                \"unknown feedback field(s) {}; only \\\"title\\\" and \\\n                 \\\"description\\\" are sent (attach files with --files)\",\n                unknown.join(\", \")\n            ));\n        }\n\n        // Validate types, not just names: a non-string field would ship to\n        // PostHog while the preview and the local record (which read via\n        // `as_str`) silently dropped it.\n        for key in [\"title\", \"description\"] {\n            if let Some(value) = obj.get(key)\n                && !value.is_string()\n            {\n                return Err(anyhow::anyhow!(\"feedback field \\\"{key}\\\" must be a string\"));\n            }\n        }\n\n        let title = obj.get(\"title\").and_then(Value::as_str).unwrap_or(\"\");\n        if title.trim().is_empty() {\n            return Err(anyhow::anyhow!(\n                \"feedback needs a title; pass --title \\\"...\\\" or a JSON payload \\\n                 with a \\\"title\\\" field\"\n            ));\n        }\n        Ok(from_json)\n    }\n\n    /// Shows exactly what a report contains and how it is attributed.\n    fn print_preview(&self, payload: &Value, identified: bool, email: Option<&str>) {\n        if identified {\n            println!(\n                \"reporting to Boundary as {}:\",","sourceCodeStart":385,"sourceCodeEnd":421,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/baml_language/crates/baml_cli/src/feedback_command.rs#L385-L421","documentation":"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.","triggerScenarios":"`baml feedback --json '{\"title\":123}'` or `--json '{\"description\":{\"text\":\"x\"}}'` — obj.get(key) exists but !value.is_string() for title or description.","commonSituations":"Building JSON payloads programmatically where numbers/booleans slip in; quoting mistakes in shell producing unquoted values; copying payloads that use null for empty fields.","solutions":["Quote the value so it is a JSON string: --json '{\"title\":\"123\"}'.","Use null by omitting the field entirely rather than passing non-string values.","Validate the payload with jq before passing it (jq -e '.title | type == \"string\"')."],"exampleFix":"// before\nbaml feedback --json '{\"title\":123}'\n// after\nbaml feedback --json '{\"title\":\"123\"}'","handlingStrategy":"type-guard","validationCode":"// ensure fields are strings before invoking\nconst p = JSON.parse(payload);\nif (p.title !== undefined && typeof p.title !== 'string') throw new Error('title must be a string');\nif (p.description !== undefined && typeof p.description !== 'string') throw new Error('description must be a string');","typeGuard":"const isStr = (v) => typeof v === 'string';\nconst validFeedback = (p) => ['title','description'].every(k => p[k] === undefined || isStr(p[k]));","tryCatchPattern":"try {\n  run(`baml feedback --json '${payload}'`);\n} catch (e) {\n  if (String(e).includes('must be a string')) {\n    const p = JSON.parse(payload);\n    ['title','description'].forEach(k => { if (p[k] !== undefined) p[k] = String(p[k]); });\n    run(`baml feedback --json '${JSON.stringify(p)}'`);\n  }\n}","preventionTips":["Coerce dynamic values to strings before building the JSON payload","Omit optional fields instead of passing null","Validate payload types with jq or a schema before invoking"],"tags":["cli","validation","json","type-mismatch"],"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"}