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

  1. Confirm the zone is listed under GET /admin/fulfillment-sets/:id before updating
  2. Use the zone ids returned by that fulfillment set's own queries
  3. 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

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


AI-assisted analysis of medusajs/medusa@5e06e544a2 (2026-08-27). Data as JSON: /api/errors/2345c6f0cefd9fcb. Report an issue: GitHub.