{"record":{"id":"3efb15e2fbd0402e","repo":"mastra-ai/mastra","slug":"preset-key-must-be-a-json-object","errorCode":null,"errorMessage":"Preset \"${key}\" must be a JSON object","messagePattern":"Preset \"(.+?)\" must be a JSON object","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/utils/validate-presets.ts","lineNumber":35,"sourceCode":"  }\n\n  const content = await readFile(absolutePath, 'utf-8');\n\n  let parsed: unknown;\n  try {\n    parsed = JSON.parse(content);\n  } catch {\n    throw new Error(`Invalid JSON in presets file: ${presetsPath}`);\n  }\n\n  if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n    throw new Error(`Presets file must contain a JSON object with named presets`);\n  }\n\n  // Validate each preset value is an object\n  for (const [key, value] of Object.entries(parsed)) {\n    if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n      throw new Error(`Preset \"${key}\" must be a JSON object`);\n    }\n  }\n\n  return content; // Return original string to preserve formatting\n}\n","sourceCodeStart":17,"sourceCodeEnd":41,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/cli/src/utils/validate-presets.ts#L17-L41","documentation":"Every top-level entry in the presets object must itself be a JSON object (the preset definition). If any value is a scalar (string, number, boolean), null, or an array, this error names the offending preset key. The message includes the key so you know exactly which entry to fix.","triggerScenarios":"`mastra dev`/`mastra studio` given a presets file where some preset maps to a non-object, e.g. `{ \"default\": null }`, `{ \"fast\": \"gpt-4\" }`, or `{ \"list\": [...] }`.","commonSituations":"Abbreviating a preset to just a model name string, nulling out an unused preset, or flattening what should be nested preset config into an array.","solutions":["Ensure each named preset is a full object of preset options, not a scalar or array.","Delete unused/null presets instead of setting them to null.","If you stored a list of variants, promote it to named object entries."],"exampleFix":"// before\n{ \"fast\": \"openai/gpt-4o\", \"unused\": null }\n// after\n{ \"fast\": { \"model\": \"openai/gpt-4o\" } }","handlingStrategy":"type-guard","validationCode":"function allPresetsAreObjects(v: unknown): boolean {\n  return typeof v === 'object' && v !== null && !Array.isArray(v) &&\n    Object.values(v).every(p => typeof p === 'object' && p !== null && !Array.isArray(p));\n}","typeGuard":"function isPresetValue(v: unknown): v is Record<string, unknown> {\n  return typeof v === 'object' && v !== null && !Array.isArray(v);\n}","tryCatchPattern":"try {\n  await loadAndValidatePresets(presetsPath);\n} catch (err) {\n  const m = /Preset \"(.+)\" must be a JSON object/.exec((err as Error).message);\n  if (m) {\n    console.error(`Preset \"${m[1]}\" must be an object; replace the scalar/array with a preset config object`);\n    process.exit(1);\n  }\n  throw err;\n}","preventionTips":["Treat each preset as a full config object; don't abbreviate to a model string.","Delete unused presets rather than setting them to null.","Add a schema check (Zod z.record(z.object({...}))) in CI."],"tags":["cli","json","config","schema-validation-failed"],"backgroundTag":"schema-validation-failed","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}