nocodb/nocodb · error · Error
Missing required columns: ${[...missingRequiredColumns].join
Error message
Missing required columns: ${[...missingRequiredColumns].join(', ')} What it means
getDataInsertObj in dataUtils reduces the row over meta.columns and accumulates any required column whose value is null/empty into missingRequiredColumns. When throwError is true and that set is non-empty, it throws 'Missing required columns: <names>' so the caller knows the row violates NOT NULL constraints before any API insert.
Source
Thrown at packages/nc-gui/utils/dataUtils.ts:217
o[childCol.title!] = ltarVal[relatedTableMeta!.columns!.find((c) => c.id === colOpt.fk_parent_column_id)!.title!]
if (o[childCol.title!] !== null && o[childCol.title!] !== undefined) missingRequiredColumns.delete(childCol.title)
}
}
}
// check all the required columns are not null
if (isColumnRequiredAndNull(col, row)) {
missingRequiredColumns.add(col.title)
}
if (!col.ai && (row?.[col.title as string] !== null || allowNullFieldIds.includes(col.id as string))) {
o[col.title as string] = row?.[col.title as string]
}
return o
}, Promise.resolve({}))
if (throwError && missingRequiredColumns.size) {
throw new Error(`Missing required columns: ${[...missingRequiredColumns].join(', ')}`)
}
return { missingRequiredColumns, insertObj }
}
// Relation types whose linked record can belong to only ONE parent record.
// Copying such a link onto a duplicated record REASSIGNS the linked record to the
// copy and silently detaches it from the original — a data-integrity hazard.
// - has-many / one-to-many: the related rows carry the FK pointing here, so
// copying moves those rows onto the duplicate.
// - one-to-one: a single record on each side, so copying steals it.
// belongs-to / many-to-one own their own FK (the parent keeps its other children)
// and many-to-many is additive, so those relationships copy safely.
const SINGLE_PARENT_RELATION_TYPES: RelationTypes[] = [
RelationTypes.HAS_MANY,
RelationTypes.ONE_TO_ONE,
RelationTypes.ONE_TO_MANY,
]View on GitHub (pinned to d3caaf4e89)
Solutions
- Pre-validate the row against meta.columns: fill or prompt for every required column before insert.
- Call getDataInsertObj with throwError=false first to collect missingRequiredColumns and show inline field errors.
- For duplicates, copy the source row's required values so the new row is never missing them.
- Ensure belongs-to relations include a valid linked record when the FK column is required.
Example fix
// before
const { insertObj } = await getDataInsertObj({ ...row, throwError: true })
// after
const { missingRequiredColumns, insertObj } = await getDataInsertObj({ ...row, throwError: false })
if (missingRequiredColumns.size) {
showFieldErrors([...missingRequiredColumns])
return
} Defensive patterns
Strategy: validation
Validate before calling
// Run with throwError=false first to collect missing fields
const { missingRequiredColumns, insertObj } = await getDataInsertObj({ ...args, throwError: false })
if (missingRequiredColumns.size) {
showFieldErrors([...missingRequiredColumns])
return
}
await insertRow(insertObj) Type guard
const rowSatisfiesRequired = (row: Record<string, any>, required: string[]): boolean => required.every((title) => row?.[title] !== undefined && row?.[title] !== null && row?.[title] !== '')
Try / catch
try {
await getDataInsertObj({ ...args, throwError: true })
} catch (e) {
if ((e as Error).message.startsWith('Missing required columns:')) {
const missing = (e as Error).message.replace('Missing required columns: ', '').split(', ')
showFieldErrors(missing)
} else throw e
} Prevention
- Pre-fill required fields from defaults or duplicated source rows.
- Run the non-throwing pass first to collect missing fields for inline UI feedback.
- Mark required columns clearly in forms and import templates.
When it happens
Trigger: Inserting or duplicating a row where one or more required (NOT NULL, no default, non-auto-increment) columns were left empty, with throwError=true. Belongs-to relations whose FK is required also land in the set when the linked value is absent.
Common situations: Form submissions missing mandatory fields; duplication of a partial row; bulk paste/import that skips required columns; LTAR belongs-to fields not populated; columns whose rqd flag is true server-side.
Related errors
- Invalid value
- ${message}
- Invalid option(s) "${options.join(', ')}" provided for colum
- Invalid filter format. Expected string or array of strings.
- ${op} is not supported.
AI-assisted analysis of nocodb/nocodb@d3caaf4e89 (2026-08-12).
Data as JSON: /api/errors/18fa04263f61a6ee.
Report an issue: GitHub.