medusajs/medusa · warning

'tab' property at the ${j} index of the 'forms' property is

Error message

'tab' property at the ${j} index of the 'forms' property is not a string literal. The 'tab' property must be a string literal, e.g. 'general' or 'attributes'.

What it means

The optional 'tab' property of a custom-field form entry must be a string literal so the plugin can statically resolve it. When 'tab' is present but its value is not a StringLiteral AST node (a variable, expression, template literal, etc.), this warning is emitted and the entry is skipped.

Source

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

    }

    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

    let tab: string | undefined

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

      tab = tabProperty.value.value
    }

    if (tab && !isValidCustomFieldFormTab(tab)) {
      logger.warn(
        `'tab' property at the ${j} index of the 'forms' property is not a valid custom field form tab for the '${model}' model. Received: ${tab}.`,
        { file }
      )
      return
    }

    const zone = zoneProperty.value.value

View on GitHub (pinned to 5e06e544a2)

Solutions

  1. Replace the expression with a literal such as tab: 'general'
  2. Remove 'tab' entirely if the default tab for the zone is acceptable
  3. Inline any imported constant value as a literal

Example fix

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

Strategy: type-guard

Validate before calling

forms.forEach((f, i) => {
  if (f.tab !== undefined && typeof f.tab !== 'string') {
    throw new Error(`forms[${i}].tab must be a string literal`)
  }
})

Type guard

const isTabLiteral = (v: unknown): v is string | undefined => v === undefined || typeof v === 'string'

Prevention

When it happens

Trigger: tab: TAB_NAME, tab: `general`, or tab: cond ? 'general' : 'attributes' inside a forms entry that already has a valid zone.

Common situations: Reusing tab constants across form modules, conditional tab selection, or copy-paste from code that computed tab names.

Related errors


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