medusajs/medusa · warning

'forms' property at the ${j} index is malformed. The 'forms'

Error message

'forms' property at the ${j} index is malformed. The 'forms' property must be an object.

What it means

The 'forms' array was found, but the element at index j is not a plain object expression (it could be a string, variable, spread, or null hole). The plugin requires every entry to be an object literal and skips non-object entries with this warning.

Source

Thrown at packages/admin/admin-vite-plugin/src/custom-fields/generate-custom-field-forms.ts:521

function getConfigs(
  path: NodePath<ExportDefaultDeclaration>,
  model: CustomFieldModel,
  index: number,
  file: string
): CustomFieldConfig[] | null {
  const formArray = getFormsArgument(path, file)

  if (!formArray) {
    logger.warn(`'forms' property is missing.`, { file })
    return null
  }

  const configs: CustomFieldConfig[] = []

  formArray.elements.forEach((element, j) => {
    if (!isObjectExpression(element)) {
      logger.warn(
        `'forms' property at the ${j} index is malformed. The 'forms' property must be an object.`,
        { file }
      )
      return
    }

    const zoneProperty = element.properties.find(
      (p) => isObjectProperty(p) && isIdentifier(p.key, { name: "zone" })
    ) as ObjectProperty | undefined

    if (!zoneProperty) {
      logger.warn(
        `'zone' property is missing from the ${j} index of the 'forms' property.`,
        { file }
      )
      return
    }

View on GitHub (pinned to 5e06e544a2)

Solutions

  1. Wrap each entry in an object literal: { zone: '...', fields: { ... } }
  2. Remove spreads; inline every form entry
  3. Delete stray values or holes in the array

Example fix

// before
forms: ['general', { zone: 'general', fields: { ...} }]
// after
forms: [{ zone: 'general', fields: { ... } }]
Defensive patterns

Strategy: type-guard

Validate before calling

forms.forEach((f, i) => {
  if (typeof f !== 'object' || f === null || Array.isArray(f)) {
    throw new Error(`forms[${i}] must be an object literal`)
  }
})

Type guard

const isFormObject = (v: unknown): v is Record<string, unknown> =>
  typeof v === 'object' && v !== null && !Array.isArray(v)

Prevention

When it happens

Trigger: forms: ['general'], forms: [...otherForms] (spread), or a trailing comma creating a hole.

Common situations: Assuming forms takes strings or paths, trying to spread shared form arrays, or copy-paste mistakes inside the array.

Understand the failure class

Related errors


AI-assisted analysis of medusajs/medusa@5e06e544a2 (2026-08-27). Data as JSON: /api/errors/296c9def9af81f61. Report an issue: GitHub.