medusajs/medusa · error · MedusaError
Could not find all existing links from data
Error message
Could not find all existing links from data
What it means
Thrown by updateRemoteLinksStep when the number of existing link rows fetched before update does not match the number of entries in the input data. The step validates that every link passed in already exists before upserting; a mismatch means at least one link could not be found.
Source
Thrown at packages/core/core-flows/src/common/steps/update-remote-links.ts:50
*/
export const updateRemoteLinksStep = createStep(
updateRemoteLinksStepId,
async (data: LinkDefinition[], { container }) => {
if (!data?.length) {
return new StepResponse([], [])
}
const link = container.resolve<Link>(ContainerRegistrationKeys.LINK)
// Fetch all existing links and throw an error if any weren't found
const dataBeforeUpdate = (await link.list(data, {
asLinkDefinition: true,
})) as LinkDefinition[]
const unequal = dataBeforeUpdate.length !== data.length
if (unequal) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Could not find all existing links from data`
)
}
// link.create here performs an upsert. By performing validation above, we can ensure
// that this method will always perform an update in these cases
await link.create(data)
return new StepResponse(data, dataBeforeUpdate)
},
async (dataBeforeUpdate, { container }) => {
if (!dataBeforeUpdate?.length) {
return
}
const link = container.resolve<Link>(ContainerRegistrationKeys.LINK)
View on GitHub (pinned to 5e06e544a2)
Solutions
- Inspect each entry in data and verify both sides (e.g. cart_id and promotion_id) still exist before calling the step
- Re-query the links via link.list() and pass the fresh link records instead of hand-built definitions
- Ensure you are creating links (createRemoteLinkStep) first if they may not exist yet
Example fix
// before
await updateRemoteLinksStep(container).run({
input: [ { [Modules.CART]: { cart_id }, [Modules.PROMOTION]: { promotion_id } , data: {...} } ],
})
// after: only update links that actually exist
const existing = await link.list(MODULES_LINK, { cart_id })
const toUpdate = existing.filter((l) => promoIds.includes(l.promotion_id))
await updateRemoteLinksStep(container).run({ input: toUpdate }) Defensive patterns
Strategy: validation
Validate before calling
const existing = await link.list(cartPromotionLink, { cart_id })
const valid = input.filter((d) => existing.some((l) => l.promotion_id === d[Modules.PROMOTION].promotion_id))
if (valid.length !== input.length) throw new Error("Some links no longer exist") Type guard
const isLinkDefinition = (d: unknown): d is LinkDefinition => !!d && typeof d === "object"
Try / catch
try { await updateRemoteLinksStep(scope).run({ input }) } catch (e) { if (e.type === MedusaError.Types.NOT_FOUND) { /* refetch links and retry with fresh data */ } throw e } Prevention
- Never hand-build link definitions from stale ids; re-query first
- Avoid partial manual deletes of one side of a link
- Log both sides of failed link lookups
When it happens
Trigger: Calling updateRemoteLinksStep (directly or via a workflow that refreshes links, e.g. cart/payment/order promotion links) where one of the link definitions references a nonexistent or already-deleted counterpart, so the pre-update query returns fewer rows than data.length.
Common situations: Passing stale link data referencing deleted records; partial deletion of one side of a link (manual DB cleanup); race where a link was removed concurrently; wrong field names in the LinkDefinition so the lookup misses.
Related errors
- Line item ${item.title} has no unit price
- Invalid step input
- Invalid step input
- Cannot associate duplicate inventory items to variant(s) ${e
- Product options are not provided for: [${missingOptionsProdu
AI-assisted analysis of medusajs/medusa@5e06e544a2 (2026-08-27).
Data as JSON: /api/errors/70750551d858cbc5.
Report an issue: GitHub.