aws-amplify / aws-amplify/amplify-hosting

Next.js SSR app 404s on SSG dynamic route with hyphen in filename

Open
#2,093 0 comments 0 reactions 0 assignees View on GitHub
ssr
Dominant language
Dockerfile
Stars
481
Forks
123
PR merge metrics
No merged PRs in 30d

Description

### Before opening, please confirm:

- [X] I have checked to see if my question is addressed in the [FAQ](https://github.com/aws-amplify/amplify-console/blob/master/FAQ.md).
- [X] I have [searched for duplicate or closed issues](https://github.com/aws-amplify/amplify-console/issues?q=is%3Aissue+).
- [X] I have read the guide for [submitting bug reports](https://github.com/aws-amplify/amplify-console/blob/master/CONTRIBUTING.md).
- [X] I have done my best to include a minimal, self-contained set of instructions for consistently reproducing the issue.

### App Id

dc3blsn6e63vx

### Region

us-east-1

### Amplify Console feature

Not applicable

### Describe the bug

When visiting the following URL: https://trying-to-reproduce-ssr-issue.dc3blsn6e63vx.amplifyapp.com/with-named/a, you will get a `404`. The filename for the dynamic route (at the `a`) has a hyphen in it: `a-a.tsx`. When the same file is available but it does not have a hyphen in the name: https://trying-to-reproduce-ssr-issue.dc3blsn6e63vx.amplifyapp.com/with-indexes/static/c, the page loads successfully.

### Expected behavior

Hyphens in dynamic route filenames do not automatically result in a `404`.

### Reproduction steps

1. Create a Next.js SSR project
2. Add a SSG/static dynamic route with a hyphen in the name `[a-a].jsx`
3. Perform a GET to that route -> 404

### Build Settings

```yaml
version: 1
frontend:
phases:
preBuild:
commands:
- yarn install
build:
commands:
- yarn build
artifacts:
baseDirectory: .next
files:
- "**/*"
cache:
paths:
- node_modules/**/*
```

### Additional information

Not sure if this is useful, but here is the `routes-manifest.js` that gets created within Lambda

```json
{
"version":3,
"pages404":true,
"basePath":"",
"redirects":[

],
"headers":[

],
"dynamicRoutes":[
{
"page":"/with-indexes/static/[c]",
"regex":"^/with\\-indexes/static/([^/]+?)(?:/)?$",
"routeKeys":{
"c":"c"
},
"namedRegex":"^/with\\-indexes/static/(?[^/]+?)(?:/)?$"
},
{
"page":"/with-indexes/static/[c]/static",
"regex":"^/with\\-indexes/static/([^/]+?)/static(?:/)?$",
"routeKeys":{
"c":"c"
},
"namedRegex":"^/with\\-indexes/static/(?[^/]+?)/static(?:/)?$"
},
{
"page":"/with-indexes/static/[c]/[d]",
"regex":"^/with\\-indexes/static/([^/]+?)/([^/]+?)(?:/)?$",
"routeKeys":{
"c":"c",
"d":"d"
},
"namedRegex":"^/with\\-indexes/static/(?[^/]+?)/(?[^/]+?)(?:/)?$"
},
{
"page":"/with-indexes/[a]",
"regex":"^/with\\-indexes/([^/]+?)(?:/)?$",
"routeKeys":{
"a":"a"
},
"namedRegex":"^/with\\-indexes/(?[^/]+?)(?:/)?$"
},
{
"page":"/with-indexes/[a]/static",
"regex":"^/with\\-indexes/([^/]+?)/static(?:/)?$",
"routeKeys":{
"a":"a"
},
"namedRegex":"^/with\\-indexes/(?
[^/]+?)/static(?:/)?$"
},
{
"page":"/with-indexes/[a]/[b]",
"regex":"^/with\\-indexes/([^/]+?)/([^/]+?)(?:/)?$",
"routeKeys":{
"a":"a",
"b":"b"
},
"namedRegex":"^/with\\-indexes/(?
[^/]+?)/(?[^/]+?)(?:/)?$"
},
{
"page":"/with-indexes/[a]/[b]/static",
"regex":"^/with\\-indexes/([^/]+?)/([^/]+?)/static(?:/)?$",
"routeKeys":{
"a":"a",
"b":"b"
},
"namedRegex":"^/with\\-indexes/(?
[^/]+?)/(?[^/]+?)/static(?:/)?$"
},
{
"page":"/with-named/static/[c-c]",
"regex":"^/with\\-named/static/([^/]+?)(?:/)?$",
"routeKeys":{
"cc":"c-c"
},
"namedRegex":"^/with\\-named/static/(?[^/]+?)(?:/)?$"
},
{
"page":"/with-named/static/[c-c]/static",
"regex":"^/with\\-named/static/([^/]+?)/static(?:/)?$",
"routeKeys":{
"cc":"c-c"
},
"namedRegex":"^/with\\-named/static/(?[^/]+?)/static(?:/)?$"
},
{
"page":"/with-named/static/[c-c]/[d-d]",
"regex":"^/with\\-named/static/([^/]+?)/([^/]+?)(?:/)?$",
"routeKeys":{
"cc":"c-c",
"dd":"d-d"
},
"namedRegex":"^/with\\-named/static/(?[^/]+?)/(?

[^/]+?)(?:/)?$"
},
{
"page":"/with-named/[a-a]",
"regex":"^/with\\-named/([^/]+?)(?:/)?$",
"routeKeys":{
"aa":"a-a"
},
"namedRegex":"^/with\\-named/(?[^/]+?)(?:/)?$"
},
{
"page":"/with-named/[a-a]/static",
"regex":"^/with\\-named/([^/]+?)/static(?:/)?$",
"routeKeys":{
"aa":"a-a"
},
"namedRegex":"^/with\\-named/(?[^/]+?)/static(?:/)?$"
},
{
"page":"/with-named/[a-a]/[b-b]",
"regex":"^/with\\-named/([^/]+?)/([^/]+?)(?:/)?$",
"routeKeys":{
"aa":"a-a",
"bb":"b-b"
},
"namedRegex":"^/with\\-named/(?[^/]+?)/(?[^/]+?)(?:/)?$"
},
{
"page":"/with-named/[a-a]/[b-b]/static",
"regex":"^/with\\-named/([^/]+?)/([^/]+?)/static(?:/)?$",
"routeKeys":{
"aa":"a-a",
"bb":"b-b"
},
"namedRegex":"^/with\\-named/(?[^/]+?)/(?[^/]+?)/static(?:/)?$"
}
],
"dataRoutes":[

],
"rewrites":[

]
}
```

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the issue with the `[a-a].jsx` SSG route and inspect the generated `routes-manifest.js` in Lambda, comparing it with the working `[c]` route. Done means a GET to `/with-named/a` succeeds when the dynamic route filename contains a hyphen, without regressing the working route.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, next.js
Domain
cloud, web-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.