medusajs/medusa · warning

'zone' property is missing from the ${j} index of the 'forms

Error message

'zone' property is missing from the ${j} index of the 'forms' property. The 'zone' property is required to load a custom field form.

What it means

The admin-vite-plugin statically analyzes your custom-field form definition (the array passed to the admin plugin's forms option) and requires each entry to declare a 'zone' string property. When an entry at index j has no 'zone' key, the plugin cannot determine where in the admin UI to inject the form, so it logs this warning and skips that entry. It is a build-time AST check, not a runtime error.

Source

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

  const formArray = getFormsArgument(path, file)

  if (!formArray) {
    return null
  }

  const forms: CustomFieldFormSection[] = []

  formArray.elements.forEach((element, j) => {
    if (!isObjectExpression(element)) {
      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. The 'zone' property is required to load a custom field form.`,
        { file }
      )
      return
    }

    if (!isStringLiteral(zoneProperty.value)) {
      logger.warn(
        `'zone' property at the ${j} index of the 'forms' property is not a string literal. The 'zone' property must be a string literal, e.g. 'general' or 'attributes'.`,
        { file }
      )
      return
    }

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

View on GitHub (pinned to 5e06e544a2)

Solutions

  1. Add zone: 'general' (or 'attributes', 'sidebars', etc.) as a string literal to the entry at the reported index of the 'forms' array
  2. Ensure the key is exactly 'zone' (lowercase) and a direct property of the form object, not nested inside 'fields'
  3. Re-run the dev/build process so the plugin re-parses the file

Example fix

// before
forms: [{ tab: 'general', fields: { myField: form.define({ ... }) } }]
// after
forms: [{ zone: 'general', tab: 'general', fields: { myField: form.define({ ... }) } }]
Defensive patterns

Strategy: validation

Validate before calling

const entry = { tab: 'general', fields: {} }
if (!('zone' in entry) || typeof entry.zone !== 'string') {
  throw new Error('forms entry is missing a string zone property')
}

Type guard

const isFormEntry = (e: unknown): e is { zone: string; fields: Record<string, unknown> } =>
  typeof e === 'object' && e !== null && 'zone' in e && typeof (e as any).zone === 'string' && 'fields' in e

Prevention

When it happens

Trigger: An object in the 'forms' array lacks the zone key, e.g. forms: [{ tab: 'general', fields: {...} }] or forms: [{ fields: {...} }] for a custom-field form module.

Common situations: Copying a form config from docs that omit 'zone', migrating from an older API where only 'tab' existed, or renaming the property to 'Zone'/'formZone'.

Related errors


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