mastra-ai/mastra · error · Error

Presets file must contain a JSON object with named presets

Error message

Presets file must contain a JSON object with named presets

What it means

loadAndValidatePresets() requires the top-level parsed JSON to be an object (a map of preset name to preset definition). If the file parses but its root is an array, a string, a number, boolean, or null, this error is thrown. Presets must be keyed by name.

Source

Thrown at packages/cli/src/utils/validate-presets.ts:29

 */
export async function loadAndValidatePresets(presetsPath: string): Promise<string> {
  const absolutePath = resolve(process.cwd(), presetsPath);

  if (!existsSync(absolutePath)) {
    throw new Error(`Presets file not found: ${absolutePath}`);
  }

  const content = await readFile(absolutePath, 'utf-8');

  let parsed: unknown;
  try {
    parsed = JSON.parse(content);
  } catch {
    throw new Error(`Invalid JSON in presets file: ${presetsPath}`);
  }

  if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
    throw new Error(`Presets file must contain a JSON object with named presets`);
  }

  // Validate each preset value is an object
  for (const [key, value] of Object.entries(parsed)) {
    if (typeof value !== 'object' || value === null || Array.isArray(value)) {
      throw new Error(`Preset "${key}" must be a JSON object`);
    }
  }

  return content; // Return original string to preserve formatting
}

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Wrap presets in a named object: `{ "presetName": { ...preset } }`.
  2. If you have an array, convert it to a map keyed by preset name before saving.
  3. Replace a null/empty placeholder file with a valid empty object `{}`.

Example fix

// before (presets.json)
[
  { "temperature": 0.7 }
]
// after
{
  "default": { "temperature": 0.7 }
}
Defensive patterns

Strategy: type-guard

Validate before calling

function isNamedPresetMap(v: unknown): v is Record<string, unknown> {
  return typeof v === 'object' && v !== null && !Array.isArray(v);
}

Type guard

function isNamedPresetMap(v: unknown): v is Record<string, unknown> {
  return typeof v === 'object' && v !== null && !Array.isArray(v) && Object.prototype.toString.call(v) === '[object Object]';
}

Try / catch

try {
  await loadAndValidatePresets(presetsPath);
} catch (err) {
  if ((err as Error).message.includes('must contain a JSON object')) {
    console.error('Presets root must be { "name": { ...preset } }, not an array or scalar');
    process.exit(1);
  }
  throw err;
}

Prevention

When it happens

Trigger: `mastra dev`/`mastra studio` given a presets file whose root is a JSON array (e.g. `[{...}]`), a bare value (`"foo"`, `42`, `true`, `null`), or an empty/null document.

Common situations: Exporting an array of presets from a script instead of a named map, writing `null` for an empty presets file, or accidentally serializing the wrong variable.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/eb4b866a24a9c220. Report an issue: GitHub.