medusajs/medusa · error · MedusaError
Service zone with id: ${req.params.zone_id} not found on ful
Error message
Service zone with id: ${req.params.zone_id} not found on fulfillment set What it means
The POST (update) /admin/fulfillment-sets/:id/service-zones/:zone_id route retrieves the fulfillment set with its service_zones relation and checks that the zone is actually attached to that set; otherwise it throws NOT_FOUND (HTTP 404), since a zone id alone is not enough — it must belong to the set.
Source
Thrown at packages/medusa/src/api/admin/fulfillment-sets/[id]/service-zones/[zone_id]/route.ts:67
export const POST = async (
req: MedusaRequest<
HttpTypes.AdminUpdateFulfillmentSetServiceZone,
HttpTypes.AdminServiceZonesParams
>,
res: MedusaResponse<AdminFulfillmentSetResponse>
) => {
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(
req.params.id,
{ relations: ["service_zones"] }
)
if (!fulfillmentSet.service_zones.find((s) => s.id === req.params.zone_id)) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Service zone with id: ${req.params.zone_id} not found on fulfillment set`
)
}
const remoteQuery = req.scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
const workflowInput = {
selector: { id: req.params.zone_id },
update: req.validatedBody,
}
await updateServiceZonesWorkflow(req.scope).run({
input: workflowInput,
})
const [fulfillment_set] = await remoteQuery(
remoteQueryObjectFromString({View on GitHub (pinned to 5e06e544a2)
Solutions
- Confirm the zone is listed under GET /admin/fulfillment-sets/:id before updating
- Use the zone ids returned by that fulfillment set's own queries
- If the zone moved sets, address it through its current parent set
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)) {
throw new Error(`Zone ${zoneId} not attached to set ${setId}`)
} Type guard
const isZoneOfSet = (set: {service_zones:{id:string}[]}, zoneId: string) =>
set.service_zones.some((z) => z.id === zoneId) Try / catch
try { await updateZone(setId, zoneId, payload) } catch (e) { if (e.statusCode === 404) { refetchSetAndZones(); retryWithCorrectIds() } else throw e } Prevention
- Keep set id and zone id paired from the same fetch
- Re-verify ownership after zone moves between sets
When it happens
Trigger: POST updating a service zone whose id exists but is attached to a different fulfillment set; stale zone id after the zone was recreated under another set.
Common situations: Reusing zone ids across fulfillment sets (e.g. shipping profile migrations); updating zones after a set was rebuilt.
Related errors
- Service zone with id: ${zone_id} not found on fulfillment se
- 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/2345c6f0cefd9fcb.
Report an issue: GitHub.