medusajs/medusa · warning

'zone' property is missing at the ${j} index of the 'display

Error message

'zone' property is missing at the ${j} index of the 'displays' property.

What it means

Iterating the displays array, the plugin requires each element object to contain a 'zone' property (the injection zone where the display renders). If an entry lacks zone, that entry is skipped with this warning naming the index j — other entries still process.

Source

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

      `'displays' is not an array. The 'displays' property must be an array of objects.`,
      { file }
    )
    return null
  }

  const displays: CustomFieldDisplay[] = []

  displayProperty.value.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 at the ${j} index of the 'displays' property.`,
        { file }
      )
      return
    }

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

    const zone = zoneProperty.value.value
    const fullPath = getDisplayEntryPath(model, zone)

    if (

View on GitHub (pinned to 5e06e544a2)

Solutions

  1. Add zone: "<injection-zone>" to the displays entry at the reported index in the flagged file
  2. Use a valid custom-field display zone string (the same ones isValidCustomFieldDisplayZone accepts)
  3. Check spelling/casing of the key — it must be exactly zone

Example fix

// before
displays: [
  { component: "/src/admin/custom-fields/brand/displays/name.tsx" },
]

// after
displays: [
  {
    zone: "general",
    component: "/src/admin/custom-fields/brand/displays/name.tsx",
  },
]
Defensive patterns

Strategy: validation

Validate before calling

cfg.displays.forEach((d, i) => {
  if (typeof d.zone !== "string") throw new Error(`displays[${i}] missing zone`)
})

Type guard

const isDisplayEntry = (d: unknown): d is { zone: string; component: string } =>
  typeof d === "object" && d !== null &&
  typeof (d as any).zone === "string" && typeof (d as any).component === "string"

Try / catch

null

Prevention

When it happens

Trigger: A displays entry like { component: "/src/admin/components/x" } with no zone key; or zone misspelled (zones, injectionZone) so the AST identifier match fails.

Common situations: Copy-paste of partial examples; assuming zone is inherited from the parent config; renaming from older API versions where the key was named differently.

Related errors


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