remix-run/remix · error · Error
upsert requires at least one value
Error message
upsert requires at least one value
What it means
compileUpsertOperation requires at least one column to insert; if the values record is empty there is nothing to upsert and the SQL would be invalid, so the compiler throws immediately.
Source
Thrown at packages/data-table-postgres/src/lib/sql-compiler.ts:212
return {
text:
'insert into ' +
quotePath(getTableName(table)) +
' (' +
quotedColumns.join(', ') +
') values ' +
valueSets.join(', ') +
compileReturningClause(returning),
values: context.values,
}
}
function compileUpsertOperation(operation: UpsertOperation, context: CompileContext): SqlStatement {
let insertColumns = Object.keys(operation.values)
let conflictTarget = operation.conflictTarget ?? [...getTablePrimaryKey(operation.table)]
if (insertColumns.length === 0) {
throw new Error('upsert requires at least one value')
}
let quotedInsertColumns = insertColumns.map((column) => quotePath(column))
let insertPlaceholders = insertColumns.map((column) =>
pushValue(context, operation.values[column]),
)
let updateValues = operation.update ?? operation.values
let updateColumns = Object.keys(updateValues)
let onConflictClause = ''
if (updateColumns.length === 0) {
onConflictClause =
' on conflict (' +
conflictTarget.map((column: string) => quotePath(column)).join(', ') +
') do nothing'
} else {
onConflictClause =View on GitHub (pinned to 9696913134)
Solutions
- Skip the upsert call when the values object has no keys
- Default to required fields or validate that the payload produced at least one column before calling upsert
- Fix upstream logic so empty payloads don't reach the database layer
Example fix
// before
await table.upsert({ ...maybeChanges }) // throws when empty
// after
if (Object.keys(changes).length > 0) {
await table.upsert(changes)
} Defensive patterns
Strategy: validation
Validate before calling
if (Object.keys(values).length === 0) { /* skip or throw a clearer error */ return } Type guard
function hasValues(v: Record<string, unknown>): boolean { return Object.keys(v).length > 0 } Prevention
- Guard upsert calls with an empty-values check
- Default required fields in the payload builder
- Reject empty form submissions before the data layer
When it happens
Trigger: Calling upsert with `{}` (empty object) as values — commonly from spreading an optional update payload that is undefined, or building values conditionally so no keys are ever set; mapping over an empty batch item.
Common situations: `...changes` where changes is empty; form submissions with no changed fields that still hit the upsert path; batch loops that generate empty rows.
Related errors
- upsert requires at least one value
- upsert requires at least one value
- insertMany() requires at least one explicit value across the
- hmr must create a channel with a close function
- hmr must create a channel with an onFileEvents function
AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27).
Data as JSON: /api/errors/211a0875d9b6409f.
Report an issue: GitHub.