medusajs/medusa · error · MedusaError
Inventory Level for Item ${id} at Location ${location_id} no
Error message
Inventory Level for Item ${id} at Location ${location_id} not found What it means
The DELETE /admin/inventory-items/:id/location_levels/:location_id route queries for an inventory_level matching both the inventory item id and the location id; no match throws NOT_FOUND (HTTP 404).
Source
Thrown at packages/medusa/src/api/admin/inventory-items/[id]/location-levels/[location_id]/route.ts:29
import { HttpTypes } from "@medusajs/framework/types"
import { refetchInventoryItem } from "../../../helpers"
export const DELETE = async (
req: MedusaRequest<{}, HttpTypes.AdminGetInventoryLocationLevelParams>,
res: MedusaResponse<HttpTypes.AdminInventoryLevelDeleteResponse>
) => {
const { id, location_id } = req.params
const query = req.scope.resolve(ContainerRegistrationKeys.QUERY)
const result = await query.graph({
entity: "inventory_level",
filters: { inventory_item_id: id, location_id },
fields: ["id", "reserved_quantity"],
})
if (!result.data.length) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Inventory Level for Item ${id} at Location ${location_id} not found`
)
}
const { id: levelId, reserved_quantity: reservedQuantity } = result.data[0]
if (reservedQuantity > 0) {
throw new MedusaError(
MedusaError.Types.NOT_ALLOWED,
`Cannot remove Inventory Level ${id} at Location ${location_id} because there are reservations at location`
)
}
const deleteInventoryLevelWorkflow = deleteInventoryLevelsWorkflow(req.scope)
await deleteInventoryLevelWorkflow.run({
input: {View on GitHub (pinned to 5e06e544a2)
Solutions
- GET the item's location levels first and delete only listed pairs
- Treat 404 on delete as already-deleted and continue idempotently
- Refresh the levels list after any delete
Defensive patterns
Strategy: try-catch
Validate before calling
const { inventory_item } = await sdk.inventoryItem.retrieve(itemId, { fields: ["location_levels.*"] })
const hasLevel = inventory_item.location_levels?.some((l) => l.location_id === locationId)
if (!hasLevel) throw new Error(`No level for ${itemId} at ${locationId}`) Type guard
const levelExists = (levels: {location_id:string}[], locId: string) =>
levels.some((l) => l.location_id === locId) Try / catch
try { await deleteLevel(itemId, locationId) } catch (e) { if (e.statusCode === 404) { /* already deleted, success */ return } throw e } Prevention
- Refresh level lists after deletes
- Treat 404 on delete as success for idempotency
When it happens
Trigger: DELETE on an inventory item/location pair where no level exists — wrong location id, level already deleted, or item never stocked at that location.
Common situations: Double-click/retry of a delete that already succeeded; UI listing stale location levels; using a stock location id from a different store.
Related errors
- Campaign with id: ${req.params.id} was not found
- Campaign with id "${req.params.id}" not found
- Claim with id: ${req.params.id} was not found
- Currency with code: ${req.params.code} was not found
- Customer group with id: ${req.params.id} not found
AI-assisted analysis of medusajs/medusa@5e06e544a2 (2026-08-27).
Data as JSON: /api/errors/b74e027a9f6ff29e.
Report an issue: GitHub.