medusajs/medusa · error · MedusaError

Promotion with id or code: ${idOrCode} was not found

Error message

Promotion with id or code: ${idOrCode} was not found

What it means

Thrown by GET /admin/promotions/:id when the remoteQuery for the promotion returns nothing. The route intentionally resolves by id OR code, so the failure means neither a promotion id nor a promotion code matched the path param.

Source

Thrown at packages/medusa/src/api/admin/promotions/[id]/route.ts:33

import { AdditionalData, HttpTypes } from "@medusajs/framework/types"

export const GET = async (
  req: AuthenticatedMedusaRequest<HttpTypes.AdminGetPromotionParams>,
  res: MedusaResponse<HttpTypes.AdminPromotionResponse>
) => {
  const idOrCode = req.params.id
  const remoteQuery = req.scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
  const queryObject = remoteQueryObjectFromString({
    entryPoint: "promotion",
    variables: {
      filters: { $or: [{ id: idOrCode }, { code: idOrCode }] },
    },
    fields: req.queryConfig.fields,
  })

  const [promotion] = await remoteQuery(queryObject)
  if (!promotion) {
    throw new MedusaError(
      MedusaError.Types.NOT_FOUND,
      `Promotion with id or code: ${idOrCode} was not found`
    )
  }

  res.status(200).json({ promotion })
}

export const POST = async (
  req: AuthenticatedMedusaRequest<
    HttpTypes.AdminUpdatePromotion & AdditionalData,
    HttpTypes.AdminGetPromotionParams
  >,
  res: MedusaResponse<HttpTypes.AdminPromotionResponse>
) => {
  const { additional_data, ...rest } = req.validatedBody
  const updatePromotions = updatePromotionsWorkflow(req.scope)
  const promotionsData = [

View on GitHub (pinned to 5e06e544a2)

Solutions

  1. List promotions (GET /admin/promotions) and confirm the id/code
  2. If the code was renamed, use the updated code from the list response
  3. In checkout code that applies codes, treat this 404 as 'invalid code' rather than an exception

Example fix

// before
const { promotion } = await sdk.admin.promotion.retrieve(code)

// after
const { promotions } = await sdk.admin.promotion.list({ q: code })
const promo = promotions.find((p) => p.code === code || p.id === code)
if (!promo) throw new Error(`No promotion for ${code}`)
Defensive patterns

Strategy: try-catch

Validate before calling

const { promotions } = await sdk.admin.promotion.list({ q: idOrCode })
if (!promotions.some((p) => p.id === idOrCode || p.code === idOrCode)) {
  throw new Error(`No promotion matches ${idOrCode}`)
}

Type guard

const isPromotion = (v: unknown): v is HttpTypes.AdminPromotion =>
  !!v && typeof v === "object" && "id" in v && "code" in v

Try / catch

try {
  return await getPromotion(idOrCode)
} catch (e: any) {
  if (e.statusCode === 404) return { valid: false, reason: "unknown code" }
  throw e
}

Prevention

When it happens

Trigger: Calling GET /admin/promotions/promo_123 (or /admin/promotions/SUMMER10) where neither an id nor a code with that value exists, or the promotion was deleted.

Common situations: Passing a code that was renamed or expired-and-deleted, mixing up campaign ids with promotion codes, or stale references after promotion re-imports.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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