payloadcms/payload · error · InvalidFieldName

Field ${field.label} has invalid name '${fieldName}'. Field

Error message

Field ${field.label} has invalid name '${fieldName}'. Field names can not include periods (.) and must be alphanumeric.

What it means

A data-affecting field's `name` contains a period (`.`). Payload uses dots as path delimiters for nested fields, relationships, queries (`where.field=...`), and the admin form, so a literal dot in a name would create ambiguous paths. Names must be alphanumeric (no dots).

Source

Thrown at packages/payload/src/fields/config/sanitize.ts:214

      }

      if (collectionConfig.auth.verify) {
        // @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
        if (reservedAPIKeyFieldNames.includes(field.name)) {
          throw new ReservedFieldName(field, field.name)
        }

        // @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
        if (reservedVerifyFieldNames.includes(field.name)) {
          throw new ReservedFieldName(field, field.name)
        }
      }
    }
  }

  // Invalid field name check
  if (fieldAffectsData && field.name.includes('.')) {
    throw new InvalidFieldName(field, field.name)
  }

  // Auto-label
  if (
    'name' in field &&
    field.name &&
    typeof field.label !== 'object' &&
    typeof field.label !== 'string' &&
    typeof field.label !== 'function' &&
    field.label !== false
  ) {
    field.label = toWords(field.name)
  }

  // Checkbox default
  if (
    field.type === 'checkbox' &&
    typeof field.defaultValue === 'undefined' &&

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Remove the dot from the name (use camelCase, snake_case, or a single token).
  2. If you actually want nesting, model it as a `group` or `array` field with a child field of the second segment.
  3. If you only need dotted access in queries, that is already supported via real nested fields — do not encode it in the name.

Example fix

// before
{ name: 'user.email', type: 'email' }
// after
{ name: 'userEmail', type: 'email' }
// or model real nesting:
{ name: 'user', type: 'group', fields: [
  { name: 'email', type: 'email' }
]}
Defensive patterns

Strategy: validation

Validate before calling

function findDottedFieldNames(fields, path = '') {
  const bad = []
  for (const f of fields) {
    if (typeof f?.name === 'string' && f.name.includes('.')) bad.push(`${path}${f.name}`)
    if (Array.isArray(f?.fields)) bad.push(...findDottedFieldNames(f.fields, `${path}${f?.name}.`))
  }
  return bad
}

Type guard

function isValidFieldName(name: unknown): name is string {
  return typeof name === 'string' && name.length > 0 && !name.includes('.')
}

Try / catch

try {
  await payload.init({ config })
} catch (err) {
  if (err?.name === 'InvalidFieldName' || /invalid name/i.test(err?.message ?? '')) {
    console.error('Field with invalid (dotted) name:', err?.data?.fieldName)
  }
  throw err
}

Prevention

When it happens

Trigger: Defining `{ name: 'user.email', type: 'text' }`, `{ name: 'meta.title', type: 'text' }`, or any field whose name includes a dot.

Common situations: Trying to namespace fields with dots to mimic nested paths; migrating from a system (e.g. some NoSQL setups) that allows dotted keys; auto-generating field names from dotted strings.

Related errors


AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12). Data as JSON: /api/errors/e76d58a2fc4f1efb. Report an issue: GitHub.