queryStringParameters not working with redirect on production

I have following redirect rule:

from = "/feed/:series/"
to = "/.netlify/functions/feed-builder/?series=:series"
status = 200

On netlify dev event.queryStringParameters.series is foobar.

On netlify deploy --prod event.queryStringParameters.series is undefined.

Any idea why?

I made a hack, but i still wonder why this works different on dev and production.

const querySeries = event.queryStringParameters.series
    ? event.queryStringParameters.series
    : event.path.split("/")[2];

I would expect that to work both places, @rane. (And welcome to out community site.)

Would you be willing to please send us a link to the site at Netlify? Also, I think I see this working now when I test (the site I think it is).

Did you get this resolved already?

Url https://5d946a94fe4ee56f05471dab--supla.netlify.com/feed/12345 should return
{"queryStringParameters":{"series":"12345"}} like it return on netlify dev.

Hi @rane, I checked the deploy you mentioned but I didn’t see a function deployed with it: https://app.netlify.com/sites/supla/functions/?scope=deploypreview:null. When I do test supla.netlify.com/feed/12345, it looks like it is working: image. Can you confirm?

Can you check url https://5d946a94fe4ee56f05471dab--supla.netlify.com/feed/1234 ? It should return {"queryStringParameters":{"series":"12345"}}, but it return {"queryStringParameters":{}}.

There are no query string parameters on that URL though, @rane .

It would look like https://site/path?param=value if there were.

Sorry if that’s a distraction from your issue but wanted to make sure we were all using the same terminology while we debug :slight_smile:

I have redirect rule and netlify dev understand that as query string parameter but production version not.

from = "/feed/:series/"
to = "/.netlify/functions/feed-builder/?series=:series"  
status = 200

You can check the source code: https://github.com/raneio/supla-rss
(check netlify.toml and functions/feed-builder.js)

ok, our documentation about query string params is only going to apply to INCOMING params - in the “from” in your example. However, I don’t see any reason why that shouldn’t work on the surface.

Could you tell us what the entire URL you see in your function (when you log it), is? Trying to understand if we just don’t fill in the value properly, or if instead we drop the ?series= part too.

Also might try it without the / at the end of the path and see if that works better:

to = "/.netlify/functions/feed-builder?series=:series"

events in dev and production

Reson why i don’t just use normal query params like ?series=123 is cache. Cache doesn’t respect anything after ? character. So it’s give same content fo ?series=123 and ?series=456.

Hi @rane, I noticed that the path’s value in the event object has the series number. While this doesn’t explain why the query params is not getting passed on, you could try using the path directly instead. Let me know if that workaround works.

I am experiencing the same issue, on netlify dev the rewrites work correctly, but in production the parameters are not passed. I do not have any prod-specific settings.

https://5f761c54ccce8e00074c4731--compassionate-khorana-4a579b.netlify.app/echo/foobar shows {}
http://localhost:8888/echo/foobar shows foobar

was this ever resolved?

rewrite looks like /echo/:msg /.netlify/functions/echo?msg=:msg 200, I can confirm that it is working in general (if I change the path name to not match the function it rewrites correctly), just the query parameters aren’t set

Hey @parkan,
I think you’ll be interested in this :slight_smile: Changes to Redirects with query string parameters are coming

@jen unfortunately the other post covers 301/302 redirects and how they handle query parameters (bringing their behavior in line with the 200 redirect that’s being used here)

the issue here is different: the rewrite rules in local dev environment allow captured path parameters to be rewritten arbitrarily into the target URL, whereas in production this does not happen (i.e. moving the :msg parameter from path to query param does not happen)

I personally really like the dev environment behavior, as it saves a lot of unnecessary path re-parsing in my function code (the original path does get passed in the event AFAIK, so it is possible to add a middleware to re-parse it, but that seems silly given that the rewrite already has the necessary information), so I’d love to see it enabled in production

however, if that is not possible it should disabled on dev so the behavior is consistent – it’s possible that it automagically works because of some express functionality that netlify dev (but not netlify’s production env) uses

I think you hit the nail on the head with your conclusion. The cli is more an emulation of how Netlify works in production. I do feel that it would be easier to change the behavior on the cli vs the production code at this time. Would you mind filing an issue about that here: https://github.com/netlify/cli/issues?

Opened a bug here: https://github.com/netlify/cli/issues/1605

FWIW I still think the production behavior is a huge limitation, as functions must be aware of their paths to be able to parse their parameters, which is brittle, verbose, and not DRY. I am almost tempted to stand up an nginx proxy to handle these rewrites for me (to keep the path parsing logic out of the function code), but that would nullify the advantages of netlify’s infrastructure.

I think the ideal behavior would be for {path} parameters in redirects to automatically populate the pathParameters property on APIGatewayEvent, as they do on AWS API Gateway.


thanks for opening an issue on that repo, @parkan. appreciate it!

I’m troubleshooting something very similar, but I think even more basic in that I’m not passing a variable in from to to and I still have the same issue. Everything works on local with netlify dev but when I push to a preview branch it doesn’t work.


Given this rule in my _redirects file:

/api/v1/search /.netlify/functions/api-v1-search?siteId=macos 200

With netlify dev on my local machine, event.queryStringParameters.siteId in my function is macos.

When pushed to a preview branch, event.queryStringParameters.siteId in my function is undefined.

More Context

I want to include a specific query parameter for a given domain, so the value gets hardcoded into the redirect itself at build time. I have a siteId variable that gets set in the build. So my _redirects template file looks like this:

/api/v1/search /.netlify/functions/api-v1-search?siteId=${siteId} 200

When this gets built, the resulting _redirects file on disk puts out a redirect rule like this:

/api/v1/search /.netlify/functions/api-v1-search?siteId=macos 200

The weird thing is, like others in this thread, the way that rule functions seems to differ between what i’m running locally with netlify dev and what is running in a preview branch build even though the redirect rule is the exact same.

Local redirect

When I run things locally using netlify dev, I get a _redirects file on disk with this rule:

/api/v1/search /.netlify/functions/api-v1-search?siteId=macos 200

Great. My function actually echos back the URL that was hit, so when i hit /api/v1/search on local using netlify dev, it gives me back this in the response:

"links": {
  "self": "https://www.macosicongallery.com/api/v1/search"

Cool. Everything works as expected locally. So I push to a preview branch.

Preview Branch redirect

So now i have the same code that was working locally, but now being built remotely by netlify’s servers and on a preview branch. Through some logging in the build, I’ve confirmed that the rule in the _redirects file is the exact same one in the local build:

/api/v1/search /.netlify/functions/api-v1-search?siteId=macos 200

But when i hit /api/v1/search on this remote preview URL – https://5fd447f2a818530007016641--macosicongallery.netlify.app/api/v1/search – it doesn’t echo back the same thing when I did it locally. I get undefined in place of where i was getting macos on my local build:

"links": {
  "self": "https://www.undefinedicongallery.com/api/v1/search"

To me, this means that the request coming into the lambda function isn’t detecting a siteId query paramenter. But i’m unsure how/where I’m doing the wrong thing, especially since it’s working locally using netlify dev (although, it sounds like from this thread, netlify dev is just an approximation, which is obviously terribly misleading in this case).

Given what Netlify’s docs say:

Query string parameters are not automatically passed to our redirect engine.

I’m still not sure why this rule isn’t working:

/api/v1/search /.netlify/functions/api-v1-search?siteId=macos 200

I’m not trying to passing query params from /api... to /.netlify/functions.... I’m just tacking on a hard-coded query param in the to, which I’m expecting to be passed to the invoked lambda. But somehow it’s being set to undefined on my preview branch.

What a great post, you clearly have the “Support Engineer mentality” in specifying your experiments and results very clearly!

The docs are a bit confusing there since we’re halfway through this work: Changes to Redirects with query string parameters are coming but TL;DR the “200” redirect is more of a “rewrite” and there query string params ARE intended to be passed on as is without a specific param1=:value1 as documented here: https://docs.netlify.com/routing/redirects/redirect-options/#query-parameters.

I think you’re saying that they are not, in fact, passed on - and I think that may be due to a bug around how we cache - we don’t always cache separately based on param, so you may have gotten a result from a prior param-less request when you made yours maybe? But, I am not so sure of that diagnosis. Could you let me know if your function is still deployed somewhere I can access it, to do some testing to see if I can figure things out? (I get a 404 at the presumed prod URL https://www.macosicongallery.com/api/v1/search)

1 Like

the query string params ARE intended to be passed on as is without a specific param1=:value1 as documented.

I think you’re saying that they are not, in fact, passed on

That’s precisely right. They do not appear to be getting passed on. Not only that, but my rule isn’t even trying to capture anything to pass along! It’s just saying redirect one path to another path and include a hard-coded parameter i.e. /path /otherpath?q=value

I have not yet deployed to production—precisely because of this bug—but have a feature branch build of the feature. You can access it here.

Of note:

I added a log to my build process which outputs the contents of my _redirects file. Looking at the build for the above linked feature branch, I can see the output of my _redirects file includes the proper rule:

Notice the rule?

/api/v1/search /.netlify/functions/api-v1-search.js?siteId=macos 200

As I would expect given what’s documented about the redirects/rewrites engine, that should be passing on any query params. But if you do a GET to the following URL:


The lambda will return an error because it’s expecting a siteId parameter but isn’t getting one.

If you include siteId explicitly in a GET request, i.e.:


It works as expected. But, as noted, I’m not expecting to have to pass that parameter explicitly given my rewrite rule, which doesn’t appear to be functioning as expected.