{"record":{"id":"e418676f01863728","repo":"medusajs/medusa","slug":"service-zone-with-id-zone-id-not-found-on-fulf","errorCode":null,"errorMessage":"Service zone with id: ${zone_id} not found on fulfillment set","messagePattern":"Service zone with id: (.+?) not found on fulfillment set","errorType":"http","errorClass":"MedusaError","httpStatus":404,"severity":"error","filePath":"packages/medusa/src/api/admin/fulfillment-sets/[id]/service-zones/[zone_id]/route.ts","lineNumber":116,"sourceCode":"  req: AuthenticatedMedusaRequest,\n  res: MedusaResponse<HttpTypes.AdminServiceZoneDeleteResponse>\n) => {\n  const { id, zone_id } = req.params\n\n  const fulfillmentModuleService = req.scope.resolve<IFulfillmentModuleService>(\n    Modules.FULFILLMENT\n  )\n\n  // ensure fulfillment set exists and that the service zone is part of it\n  const fulfillmentSet = await fulfillmentModuleService.retrieveFulfillmentSet(\n    id,\n    {\n      relations: [\"service_zones\"],\n    }\n  )\n\n  if (!fulfillmentSet.service_zones.find((s) => s.id === zone_id)) {\n    throw new MedusaError(\n      MedusaError.Types.NOT_FOUND,\n      `Service zone with id: ${zone_id} not found on fulfillment set`\n    )\n  }\n\n  await deleteServiceZonesWorkflow(req.scope).run({\n    input: { ids: [zone_id] },\n  })\n\n  res.status(200).json({\n    id: zone_id,\n    object: \"service_zone\",\n    deleted: true,\n    parent: fulfillmentSet as unknown as HttpTypes.AdminFulfillmentSet,\n  })\n}\n","sourceCodeStart":98,"sourceCodeEnd":133,"githubUrl":"https://github.com/medusajs/medusa/blob/5e06e544a296b9033f20f71f11c559f81a0e5739/packages/medusa/src/api/admin/fulfillment-sets/[id]/service-zones/[zone_id]/route.ts#L98-L133","documentation":"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.","triggerScenarios":"DELETE on a zone id that is not attached to the given fulfillment set id.","commonSituations":"Scripts deleting zones by id while passing a mismatched fulfillment set path param; UI sending the set id of a different profile.","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"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const set = await fulfillmentModuleService.retrieveFulfillmentSet(setId, { relations: [\"service_zones\"] })\nif (!set.service_zones.some((z) => z.id === zoneId)) return // already gone / wrong set: no-op","typeGuard":"const isDeletableZone = (set: {service_zones:{id:string}[]}, zoneId: string) =>\n  set.service_zones.some((z) => z.id === zoneId)","tryCatchPattern":"try { await deleteZone(setId, zoneId) } catch (e) { if (e.statusCode === 404) { /* treat as already deleted */ return } throw e }","preventionTips":["Make zone deletion idempotent by swallowing 404","Send path params from the same row object in UIs"],"tags":["admin-api","fulfillment","service-zones","delete","ownership-check"],"backgroundTag":"http-404-nested-resource-not-found","analyzedSha":"5e06e544a296b9033f20f71f11c559f81a0e5739","analyzedAt":"2026-08-27T07:24:39.599Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}