payloadcms/payload · error · MissingFieldType
Field "${field.name}" is either missing a field type or it d
Error message
Field "${field.name}" is either missing a field type or it does not match an available field type What it means
Thrown by Payload's field sanitizer (sanitize.ts:168) when a field definition has no `type` property, or a type that does not resolve to a known Payload field type. Every field in a collection, global, array, block, group, or tab must declare a `type` so Payload can derive the DB schema, admin UI, and validators. The check runs on every field during `payload.init()` / config sanitization, so this fails at boot, not at request time.
Source
Thrown at packages/payload/src/fields/config/sanitize.ts:168
parentIsLocalized,
parentSchemaPath,
polymorphicJoins,
requireFieldLevelRichTextEditor,
richTextSanitizers,
validRelationships,
}: SanitizeFieldArgs): SanitizeFieldResult => {
const result: SanitizeFieldResult = {}
if ('_sanitized' in field && field._sanitized === true) {
return result
}
if ('_sanitized' in field) {
field._sanitized = true
}
if (!field.type) {
throw new MissingFieldType(field)
}
const fieldAffectsData = _fieldAffectsData(field)
const { indexPath, schemaPath } = getFieldPaths({
field,
index,
parentIndexPath,
parentSchemaPath,
})
// Reserved field name checks
if (isTopLevelField && fieldAffectsData && field.name) {
if (collectionConfig && collectionConfig.upload) {
if (reservedBaseUploadFieldNames.includes(field.name)) {
throw new ReservedFieldName(field, field.name)
}
}View on GitHub (pinned to 00c58b35c0)
Solutions
- Add the `type` property to the offending field definition (e.g. `type: 'text'`).
- Confirm the type string is one of Payload's known types (text, number, textarea, select, relationship, upload, array, blocks, group, tabs, date, checkbox, json, code, point, richText, email, join, ui, slug, virtual, etc.).
- If the field came from a spread/import, inspect the source object to ensure it carries `type`.
- If using a custom field plugin, make sure it returns a fully-formed field including `type`.
Example fix
// before
fields: [
{ name: 'title' }
]
// after
fields: [
{ name: 'title', type: 'text' }
] Defensive patterns
Strategy: validation
Validate before calling
import { reservedBaseUploadFieldNames } from 'payload/reservedFieldNames' // pseudocode
const KNOWN_TYPES = new Set(['text','number','textarea','select','relationship','upload','array','blocks','group','tabs','date','checkbox','json','code','point','richText','email','join','ui','slug','virtual','radio','password'])
function assertFieldsHaveType(fields: any[], path = '') {
for (const f of fields) {
if (!f || typeof f.type !== 'string' || !KNOWN_TYPES.has(f.type)) {
throw new Error(`Field at ${path || 'root'} is missing a valid type: ${JSON.stringify(f?.name)}`)
}
for (const k of ['fields','tabs']) if (Array.isArray(f[k])) assertFieldsHaveType(f[k], `${path}.${f.name}.${k}`)
if (Array.isArray(f.blocks)) for (const b of f.blocks) if (b?.fields) assertFieldsHaveType(b.fields, `${path}.${f.name}.blocks.${b.slug}`)
}
}
// call against your config collections/globals before buildConfig():
// collections.forEach(c => assertFieldsHaveType(c.fields, c.slug)) Type guard
type AnyField = { name?: string; type?: string }
function hasValidType(f: AnyField): f is AnyField & { type: string } {
return typeof f?.type === 'string' && f.type.length > 0
}
// usage: if (!hasValidType(field)) throw new Error('field missing type') Try / catch
try {
await payload.init({ config })
} catch (err) {
if (err?.name === 'MissingFieldType' || /missing a field type/i.test(err?.message ?? '')) {
// err.data.field exposes the offending field object — log it to locate the config entry
console.error('Field missing type:', err?.data?.field)
}
throw err
} Prevention
- Type your field arrays as `Field[]` (from payload) so TypeScript rejects typeless objects at compile time.
- Write a small unit test that sanitizes your config in isolation and fails fast on missing types.
- When spreading partial field configs, type them as `Field` so omissions surface.
When it happens
Trigger: Defining a field as `{ name: 'title' }` with no `type`; spreading a partial field object that omits type (`...baseField` where baseField has no type); returning a field from a plugin/hook that returns `{ name, label }` only; passing a UI field config that lost its `type` during a refactor.
Common situations: Copy-pasting a field and deleting the type line by accident; loosely typed field variables (`Field` widened to `any`); upgrading Payload where a previously-inferred type now must be explicit; building fields dynamically from a config map that forgets the type key.
Related errors
- Field ${field.label} has reserved name '${fieldName}'.
- Field ${field.label} has invalid name '${fieldName}'. Field
- Field "${field.name}" of type "${field.type}" has an empty r
- A field with the name '${fieldName}' was found multiple time
- Virtual field ${virtualField.name} in ${globalConfig ? `glob
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/5ec3e65dde7be0ec.
Report an issue: GitHub.