{"record":{"id":"33c77006ed1b81f5","repo":"medusajs/medusa","slug":"the-fields-property-is-missing-at-the-j-index","errorCode":null,"errorMessage":"The 'fields' property is missing at the ${j} index of the 'forms' property. The 'fields' property is required to load a custom field form.","messagePattern":"The 'fields' property is missing at the (.+?) index of the 'forms' property\\. The 'fields' property is required to load a custom field form\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/admin/admin-vite-plugin/src/custom-fields/generate-custom-field-forms.ts","lineNumber":354,"sourceCode":"    const fullPath = getFormEntryFieldPath(model, zone, tab)\n\n    if (\n      !isValidCustomFieldFormZone(zone) ||\n      !isValidCustomFieldFormFieldPath(fullPath)\n    ) {\n      logger.warn(\n        `'zone' and 'tab' properties at the ${j} index of the 'forms' property are not a valid for the '${model}' model. Received: { zone: ${zone}, tab: ${tab} }.`,\n        { file }\n      )\n      return\n    }\n\n    const fieldsObject = element.properties.find(\n      (p) => isObjectProperty(p) && isIdentifier(p.key, { name: \"fields\" })\n    ) as ObjectProperty | undefined\n\n    if (!fieldsObject) {\n      logger.warn(\n        `The 'fields' property is missing at the ${j} index of the 'forms' property. The 'fields' property is required to load a custom field form.`,\n        { file }\n      )\n      return\n    }\n\n    const fields: CustomFieldFormField[] = []\n\n    if (!isObjectExpression(fieldsObject.value)) {\n      logger.warn(\n        `The 'fields' property at the ${j} index of the 'forms' property is malformed. The 'fields' property must be an object.`,\n        { file }\n      )\n      return\n    }\n\n    fieldsObject.value.properties.forEach((field) => {\n      if (!isObjectProperty(field) || !isIdentifier(field.key)) {","sourceCodeStart":336,"sourceCodeEnd":372,"githubUrl":"https://github.com/medusajs/medusa/blob/5e06e544a296b9033f20f71f11c559f81a0e5739/packages/admin/admin-vite-plugin/src/custom-fields/generate-custom-field-forms.ts#L336-L372","documentation":"Each entry in the 'forms' array must declare a 'fields' object mapping field names to their form definitions. When the entry at index j has no 'fields' key, there is nothing to render, so the plugin warns and skips the entry.","triggerScenarios":"forms: [{ zone: 'general', tab: 'general' }] with no fields key, or naming it 'field', 'components', or 'inputs'.","commonSituations":"Skeleton config committed before adding fields, renaming the key while refactoring, or nesting fields one level too deep.","solutions":["Add a fields object: fields: { myField: form.define({ ... }) } or { myField: { ... } }","Ensure 'fields' is a sibling of 'zone'/'tab', not nested inside them","Check for typos in the property name"],"exampleFix":"// before\nforms: [{ zone: 'general', tab: 'general' }]\n// after\nforms: [{ zone: 'general', tab: 'general', fields: { subtitle: form.define({ label: 'Subtitle' }) } }]","handlingStrategy":"validation","validationCode":"if (!f.fields || typeof f.fields !== 'object' || Array.isArray(f.fields)) {\n  throw new Error('every forms entry needs a fields object')\n}","typeGuard":"const hasFields = (f: unknown): f is { fields: Record<string, unknown> } =>\n  typeof f === 'object' && f !== null && 'fields' in (f as object)","tryCatchPattern":null,"preventionTips":["Use a shared TypeScript type for form entries with required fields so the compiler catches omissions"],"tags":["admin","custom-fields","config-validation"],"backgroundTag":"admin-custom-field-form-validation","analyzedSha":"5e06e544a296b9033f20f71f11c559f81a0e5739","analyzedAt":"2026-08-27T07:24:39.599Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}