medusajs/medusa · error · MedusaError
23503
23503
Error message
You tried to set relationship ${info?.keys.map((key, i) => `${key}: ${info.values[i]}`)}, but such entity does not exist What it means
PostgreSQL error 23503 (foreign_key_violation) was caught by Medusa's dbErrorMapper and re-thrown as a MedusaError of type NOT_FOUND. It occurs when an INSERT/UPDATE sets a foreign key column to a value that has no matching row in the related table — i.e. you tried to link entity A to entity B whose ID does not exist. The message lists the offending key/value pairs extracted from the constraint info.
Source
Thrown at packages/core/utils/src/dal/mikro-orm/db-error-mapper.ts:71
}
if (
err instanceof InvalidFieldNameException ||
(err as any).code === "42703"
) {
const userFriendlyMessage = err.message.match(/(column.*)/)?.[0]
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
userFriendlyMessage ?? err.message
)
}
if (
err instanceof ForeignKeyConstraintViolationException ||
(err as any).code === "23503"
) {
const info = getConstraintInfo(err)
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`You tried to set relationship ${info?.keys.map(
(key, i) => `${key}: ${info.values[i]}`
)}, but such entity does not exist`
)
}
throw err
}
const getConstraintInfo = (err: any) => {
const detail = err.detail as string
if (!detail) {
return null
}
const [keys, values] = detail.match(/\([^\(]*\)/g) || []
View on GitHub (pinned to 5e06e544a2)
Solutions
- Check that every relation ID you are setting actually exists before the write (query the related service by ID first, or validate incoming IDs).
- If the related record was deleted intentionally, clear/null the relation on referencing records first, or stop referencing it in your payload.
- If you must delete the related record, use the module's soft-delete or cascade rules instead of raw SQL deletes that bypass FK cleanup.
- Re-seed or fix stale fixture/export IDs when promoting data between environments.
Example fix
// before
await orderService.updateOrders([{ id: orderId, sales_channel_id: "sc_dead" }])
// after
const sc = await salesChannelService.retrieveSalesChannel("sc_dead") // throws NOT_FOUND early if missing
await orderService.updateOrders([{ id: orderId, sales_channel_id: sc.id }]) Defensive patterns
Strategy: validation
Validate before calling
const ids = [payload.customer_id, payload.sales_channel_id].filter(Boolean)
const existing = await someService.list({ id: ids })
if (existing.length !== new Set(ids).size) {
throw new MedusaError(MedusaError.Types.NOT_FOUND, "Referenced entity does not exist")
} Try / catch
try {
await service.create(payload)
} catch (err) {
if (err instanceof MedusaError && err.type === MedusaError.Types.NOT_FOUND && /such entity does not exist/.test(err.message)) {
// parse key/value pairs, validate or clear the relation, then retry
}
throw err
} Prevention
- Validate all incoming relation IDs against their services before writing.
- Avoid raw SQL hard-deletes of entities referenced by foreign keys; use module soft-deletes.
- Log the offending key/value pairs from the message when it fires to pinpoint the payload field.
When it happens
Trigger: Creating or updating a record with a relation ID that doesn't exist: e.g. creating a cart with customer_id: 'cus_x' after that customer was deleted, updating an order's sales_channel_id to a removed channel, or upserting a product with category_ids containing stale IDs.
Common situations: Hard-deleting a related record while other rows still reference it (soft-deleted modules vs raw SQL deletes); using fixture/seed IDs that no longer exist across environments; passing an empty-string or undefined-coerced ID into a relation field; race where the related entity is deleted between read and write.
Related errors
- The specified PostgreSQL database does not exist. Please cre
- Migrations missing. Please run 'medusa migrations run' and t
- 42703
- Failed to setup database; install PostgresQL or make sure to
- --config file must be of type .json or .yaml - ${configFileC
AI-assisted analysis of medusajs/medusa@5e06e544a2 (2026-08-27).
Data as JSON: /api/errors/caa8bb582a7b6e18.
Report an issue: GitHub.