medusajs/medusa · error · MedusaError
Service zone with id: ${zone_id} not found on fulfillment se
Error message
Service zone with id: ${zone_id} not found on fulfillment set What it means
The DELETE /admin/fulfillment-sets/:id/service-zones/:zone_id route performs the same ownership check as the update route: it loads the fulfillment set with service_zones and throws NOT_FOUND (HTTP 404) if the zone is not among them, preventing deletion of zones belonging to other sets.
Source
Thrown at packages/medusa/src/api/admin/fulfillment-sets/[id]/service-zones/[zone_id]/route.ts:116
req: AuthenticatedMedusaRequest,
res: MedusaResponse<HttpTypes.AdminServiceZoneDeleteResponse>
) => {
const { id, zone_id } = req.params
const fulfillmentModuleService = req.scope.resolve<IFulfillmentModuleService>(
Modules.FULFILLMENT
)
// ensure fulfillment set exists and that the service zone is part of it
const fulfillmentSet = await fulfillmentModuleService.retrieveFulfillmentSet(
id,
{
relations: ["service_zones"],
}
)
if (!fulfillmentSet.service_zones.find((s) => s.id === zone_id)) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Service zone with id: ${zone_id} not found on fulfillment set`
)
}
await deleteServiceZonesWorkflow(req.scope).run({
input: { ids: [zone_id] },
})
res.status(200).json({
id: zone_id,
object: "service_zone",
deleted: true,
parent: fulfillmentSet as unknown as HttpTypes.AdminFulfillmentSet,
})
}
View on GitHub (pinned to 5e06e544a2)
Solutions
- Fetch the fulfillment set's zones first and delete using matching ids
- Validate both path params come from the same source object in the client
- Handle 404 as a no-op 'already gone/does not belong' outcome for idempotent deletes
Defensive patterns
Strategy: validation
Validate before calling
const set = await fulfillmentModuleService.retrieveFulfillmentSet(setId, { relations: ["service_zones"] })
if (!set.service_zones.some((z) => z.id === zoneId)) return // already gone / wrong set: no-op Type guard
const isDeletableZone = (set: {service_zones:{id:string}[]}, zoneId: string) =>
set.service_zones.some((z) => z.id === zoneId) Try / catch
try { await deleteZone(setId, zoneId) } catch (e) { if (e.statusCode === 404) { /* treat as already deleted */ return } throw e } Prevention
- Make zone deletion idempotent by swallowing 404
- Send path params from the same row object in UIs
When it happens
Trigger: DELETE on a zone id that is not attached to the given fulfillment set id.
Common situations: Scripts deleting zones by id while passing a mismatched fulfillment set path param; UI sending the set id of a different profile.
Related errors
- Service zone with id: ${req.params.zone_id} not found on ful
- Service zone with id: ${req.params.zone_id} not found
- Sales channels can only be associated with publishable API k
- Campaign with id: ${req.params.id} was not found
- Campaign with id "${req.params.id}" not found
AI-assisted analysis of medusajs/medusa@5e06e544a2 (2026-08-27).
Data as JSON: /api/errors/e418676f01863728.
Report an issue: GitHub.