{"record":{"id":"40d259c63ebe115c","repo":"medusajs/medusa","slug":"requested-sales-channel-is-not-part-of-the-publish","errorCode":null,"errorMessage":"Requested sales channel is not part of the publishable key","messagePattern":"Requested sales channel is not part of the publishable key","errorType":"validation","errorClass":"MedusaError","httpStatus":400,"severity":"error","filePath":"packages/medusa/src/api/utils/middlewares/products/filter-by-valid-sales-channels.ts","lineNumber":32,"sourceCode":"    req.publishable_key_context\n\n  let { sales_channel_id: idsFromRequest = [] } = req.validatedQuery as {\n    sales_channel_id: string | string[]\n  }\n\n  idsFromRequest = Array.isArray(idsFromRequest)\n    ? idsFromRequest\n    : [idsFromRequest]\n\n  // If all sales channel ids are not in the publishable key, we throw an error\n  if (idsFromRequest.length) {\n    const uniqueInParams = arrayDifference(\n      idsFromRequest,\n      idsFromPublishableKey\n    )\n\n    if (uniqueInParams.length) {\n      throw new MedusaError(\n        MedusaError.Types.INVALID_DATA,\n        `Requested sales channel is not part of the publishable key`\n      )\n    }\n\n    return idsFromRequest\n  }\n\n  if (idsFromPublishableKey?.length) {\n    return idsFromPublishableKey\n  }\n\n  return []\n}\n\n// Selection of sales channels happens in the following priority:\n// - If a publishable API key is passed, we take the sales channels attached to it and filter them down based on the query params\n// - If a sales channel id is passed through query params, we use that","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/medusajs/medusa/blob/5e06e544a296b9033f20f71f11c559f81a0e5739/packages/medusa/src/api/utils/middlewares/products/filter-by-valid-sales-channels.ts#L14-L50","documentation":"Thrown by the store product middleware when a request supplies sales_channel_id filter values that are not among the sales channels attached to the publishable key used on the request. Medusa scopes store requests to the publishable key's sales channels, so asking for products in any other channel is rejected as invalid data. It is raised before the query runs, in transformAndValidateSalesChannelIds.","triggerScenarios":"Calling GET /store/products?sales_channel_id=sc_xxx (single value or comma/array list) where sc_xxx is not linked to the publishable key sent in the x-publishable-api-key header. Any store product/variant endpoint that goes through filterByValidSalesChannels.","commonSituations":"Copy-pasting a sales channel id from another environment (staging vs prod), using a newly created sales channel without attaching it to the publishable key, or sending the admin sales channel id instead of the store one.","solutions":["Verify the sales channel ids in the request are attached to the publishable key: check the publishable key's sales_channels in Admin (Settings > Publishable API Keys) or via /admin/api-keys","Remove the sales_channel_id filter and let the publishable key's channels scope the query","If the channel genuinely should be accessible, add it to the publishable key in the admin and retry"],"exampleFix":"// before\nGET /store/products?sales_channel_id=sc_other_env\nx-publishable-api-key: pk_live_...\n\n// after\nGET /store/products?sales_channel_id=sc_linked_channel\nx-publishable-api-key: pk_live_...","handlingStrategy":"validation","validationCode":"// before the request, compare desired channel ids with the key's channels\nconst keyChannels = await fetch('/store/sales-channels', {\n  headers: { 'x-publishable-api-key': PK },\n}).then(r => r.json()).then(d => d.sales_channels.map(c => c.id))\nconst wanted = ['sc_x']\nconst valid = wanted.every(id => keyChannels.includes(id))\nif (!valid) throw new Error('sales channel not in publishable key')","typeGuard":"const isValidSalesChannelId = (\n  id: string,\n  keyChannelIds: string[]\n): boolean => keyChannelIds.includes(id)","tryCatchPattern":"try {\n  await sdk.store.product.list({ sales_channel_id: ids })\n} catch (e) {\n  if (e.type === 'invalid_data' && /not part of the publishable key/.test(e.message)) {\n    // refresh channel list, drop the filter, or surface a config error\n  }\n  throw e\n}","preventionTips":["Fetch and cache the publishable key's sales channels at storefront startup and validate filters against them","Never hardcode sales channel ids across environments; resolve them per environment"],"tags":["sales-channel","publishable-key","store-api","validation"],"backgroundTag":"publishable-key-scope-mismatch","analyzedSha":"5e06e544a296b9033f20f71f11c559f81a0e5739","analyzedAt":"2026-08-27T07:24:39.599Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}