Clicking the App from NavigationMenu throws "Please supply a shop param" error.

Topic summary

Issue: After integrating Shopify App Bridge’s NavigationMenu in a Next.js app (with Polaris and shopify-nextjs-toolbox), clicking back into the app triggers the error: “Please supply a ‘shop’ param.”

Context: The app sets a host value from URL params (prefers host; else base64-encodes shop) in pages/_app.js and uses a RoutePropagator for App Bridge redirects. Pages render fine initially. Screenshots and a screen recording illustrate the error state.

Root cause (latest update): The error originates from the app’s own endpoint ../api/auth/start.js. That route explicitly checks req.query.shop and responds with the error when it’s missing:

  • If (!req.query.shop) → respond “Please supply a ‘shop’ param”.

Implication: The return path triggered by the NavigationMenu/redirect does not include the shop query parameter, so the auth endpoint rejects the request. The app currently relies on host or shop in the URL, but the endpoint specifically requires shop.

Resolution/next steps: Ensure the redirect to the auth endpoint includes ?shop=… or modify the endpoint to accept/derive shop from host (e.g., decode host) when shop is absent. Status: Resolved by identifying internal source; requires app-side parameter handling adjustment.

Summarized with AI on January 14. AI used: gpt-5.

I’m trying to implement NavigationMenu.

My code is pretty simple.

pages/_app.js

import enTranslations from '@shopify/polaris/locales/en.json'
import { AppProvider, Frame, FooterHelp, Link } from '@shopify/polaris'
import { useShopOrigin, ShopifyAppBridgeProvider } from 'shopify-nextjs-toolbox'
import { useCallback, useEffect, useState } from 'react'
import { useRouter } from 'next/router'

import '@shopify/polaris/build/esm/styles.css'
import '../styles.css'

import RoutePropagator from 'pages/route-propagator'
import ShopProvider from '../contexts/ShopContext'
import SideNavigation from '../components/shared/SideNavigation'

function MyApp({ Component, pageProps }) {
  const shopOrigin = useShopOrigin()
  const router = useRouter()

  let host
  if (typeof window !== 'undefined') {
    // Get the query parameters from window.location.search
    const searchParams = new URLSearchParams(window.location.search)
    if (searchParams?.host) {
      host = searchParams.host
    } else if (searchParams?.shop) {
      host = btoa(searchParams.shop)
    }
  }

  if (typeof window === 'undefined' || !window.location || !shopOrigin) {
    return <>
  }

  const config = {
    apiKey: process.env.NEXT_PUBLIC_SHOPIFY_API_PUBLIC_KEY,
    forceRedirect: true,
  }

  return (
    
  )
}

export default MyApp

pages/route-propagator.js

import { useContext, useEffect } from 'react'
import Router, { useRouter } from 'next/router'
import {
  Context as AppBridgeContext,
  RoutePropagator as ShopifyRoutePropagator,
} from '@shopify/app-bridge-react'
import { Redirect } from '@shopify/app-bridge/actions'

function RoutePropagator() {
  const router = useRouter()
  const { route, asPath } = router
  const appBridge = useContext(AppBridgeContext)

  useEffect(() => {
    appBridge.subscribe(Redirect.Action.APP, (payload) => {
      Router.push(payload.path)
    })
  }, [appBridge])

  return appBridge && route ? (
    

pages/home.js

```javascript
function HomePage() {
  return <>I am home!
}

export default HomePage

pages/page1/index.js

import { Layout, Page } from '@shopify/polaris'

const Page1 = () => (
  
)

export default Page1

pages/page2/index.js

import { Layout, Page } from '@shopify/polaris'

const Page2 = () => (
  
)

export default Page2

It is looking good.

…until I click back on the app where it throws the following error:

Here a sample screen recording:

https://www.awesomescreenshot.com/video/22070718?key=b9c66db8db9a6bc78c9082892d30e317

Does anyone know what I’m missing? Can you point me in the right direction? Thanks!

The error was being returned from within the app. We have an endpoint in ../api/auth/start.js.

In the code, it checks if the shop is included in the request and it throws that error if it isn’t.

export default async (req, res) => {
  if (!req.query.shop) {
    res.send("Please supply a 'shop' param")
    return
  }
  ...
}