medusajs/medusa · warning
The 'fields' property at the ${j} index of the 'forms' prope
Error message
The 'fields' property at the ${j} index of the 'forms' property is malformed. The 'fields' property must be an object. What it means
The 'fields' property of a form entry must be a plain object expression mapping field names to definitions. If the AST value is an array, identifier, call, or anything other than an ObjectExpression, 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:364
return
}
const fieldsObject = element.properties.find(
(p) => isObjectProperty(p) && isIdentifier(p.key, { name: "fields" })
) as ObjectProperty | undefined
if (!fieldsObject) {
logger.warn(
`The 'fields' property is missing at the ${j} index of the 'forms' property. The 'fields' property is required to load a custom field form.`,
{ file }
)
return
}
const fields: CustomFieldFormField[] = []
if (!isObjectExpression(fieldsObject.value)) {
logger.warn(
`The 'fields' property at the ${j} index of the 'forms' property is malformed. The 'fields' property must be an object.`,
{ file }
)
return
}
fieldsObject.value.properties.forEach((field) => {
if (!isObjectProperty(field) || !isIdentifier(field.key)) {
return
}
const name = field.key.name
if (
!isObjectExpression(field.value) &&
!(
isCallExpression(field.value) &&
isMemberExpression(field.value.callee) &&View on GitHub (pinned to 5e06e544a2)
Solutions
- Change 'fields' to an inline object literal keyed by field name
- Inline imported/constant field definitions directly into the config
- Use form.define({...}) per field key if defining component-backed fields
Example fix
// before
forms: [{ zone: 'general', fields: [myFieldDef] }]
// after
forms: [{ zone: 'general', fields: { myField: form.define({ ... }) } }] Defensive patterns
Strategy: type-guard
Validate before calling
if (Array.isArray(f.fields) || typeof f.fields !== 'object') {
throw new Error('fields must be a plain object, not an array')
} Type guard
const isPlainObject = (v: unknown): v is Record<string, unknown> => typeof v === 'object' && v !== null && !Array.isArray(v)
Prevention
- Remember the shape: forms is an array of { zone, fields: { name: def } }; only the outer forms is an array
When it happens
Trigger: fields: [field1, field2], fields: myFields (imported variable), or fields: getFields().
Common situations: Assuming fields is a list like the outer 'forms' array, or trying to DRY configs by extracting the fields object to a variable (unsupported because parsing is static).
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- 'forms' property at the ${j} index is malformed. The 'forms'
- 'fields' property at the ${j} index of the 'forms' property
- The 'forms' property is malformed. The 'forms' property must
- 'zone' property is missing from the ${j} index of the 'forms
- 'zone' property at the ${j} index of the 'forms' property is
AI-assisted analysis of medusajs/medusa@5e06e544a2 (2026-08-27).
Data as JSON: /api/errors/3c001d70a9b76ec4.
Report an issue: GitHub.