Skip to content

Nuxt prerender pages fail to load on refresh on amplify hosting. #14606

@jmarshall9120

Description

@jmarshall9120

Before opening, please confirm:

JavaScript Framework

Vue

Amplify APIs

Not applicable

Amplify Version

v6

Amplify Categories

hosting

Backend

Amplify Gen 2

Environment information

# 
  System:
    OS: Windows 11 10.0.26100
    CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
    Memory: 5.97 GB / 31.74 GB
  Binaries:
    Node: 20.12.2 - C:\Program Files\nodejs\node.EXE
    Yarn: 4.3.1 - C:\Program Files\nodejs\yarn.CMD
    npm: 10.5.0 - C:\Program Files\nodejs\npm.CMD
    pnpm: 9.13.1 - C:\Program Files\nodejs\pnpm.CMD
  Browsers:
    Chrome: 141.0.7390.108
    Edge: Chromium (140.0.3485.54)
    Internet Explorer: 11.0.26100.1882
  npmPackages:
    @aws-amplify/backend: ^1.16.1 => 1.16.1
    @aws-amplify/backend-cli: ^1.8.0 => 1.8.0
    @aws-amplify/cli: ^14.0.0 => 14.0.0
    @aws-amplify/ui-vue: ^4.3.3 => 4.3.3
    @aws-sdk/client-s3: ^3.917.0 => 3.917.0
    @mdi/font: ^7.4.47 => 7.4.47
    @nuxt/eslint: ^1.9.0 => 1.9.0
    aws-amplify: ^6.15.5 => 6.15.5
    aws-amplify/adapter-core:  undefined ()
    aws-amplify/adapter-core/internals:  undefined ()
    aws-amplify/analytics:  undefined ()
    aws-amplify/analytics/kinesis:  undefined ()
    aws-amplify/analytics/kinesis-firehose:  undefined ()
    aws-amplify/analytics/personalize:  undefined ()
    aws-amplify/analytics/pinpoint:  undefined ()
    aws-amplify/api:  undefined ()
    aws-amplify/api/internals:  undefined ()
    aws-amplify/api/server:  undefined ()
    aws-amplify/auth:  undefined ()
    aws-amplify/auth/cognito:  undefined ()
    aws-amplify/auth/cognito/server:  undefined ()
    aws-amplify/auth/enable-oauth-listener:  undefined ()
    aws-amplify/auth/server:  undefined ()
    aws-amplify/data:  undefined ()
    aws-amplify/data/server:  undefined ()
    aws-amplify/datastore:  undefined ()
    aws-amplify/in-app-messaging:  undefined ()
    aws-amplify/in-app-messaging/pinpoint:  undefined ()
    aws-amplify/push-notifications:  undefined ()
    aws-amplify/push-notifications/pinpoint:  undefined ()
    aws-amplify/storage:  undefined ()
    aws-amplify/storage/s3:  undefined ()
    aws-amplify/storage/s3/server:  undefined ()
    aws-amplify/storage/server:  undefined ()
    aws-amplify/utils:  undefined ()
    eslint: ^9.34.0 => 9.34.0
    isomorphic-dompurify: ^2.26.0 => 2.26.0
    marked: ^16.2.1 => 16.2.1
    nuxt: ^4.0.3 => 4.0.3
    ofetch: ^1.4.1 => 1.4.1
    typescript: ^5.9.2 => 5.9.2 (4.4.4, 4.9.5)
    vite-plugin-vuetify: ^2.1.2 => 2.1.2
    vue: ^3.5.20 => 3.5.20
    vue-router: ^4.5.1 => 4.5.1
    vuetify: ^3.9.6 => 3.9.6
  npmGlobalPackages:
    @aws-amplify/cli: 13.0.1

Describe the bug

Facts:

Prerender links are not redirecting from path/ to path/index.html by default.
Retrieving both endpoints hit CloudFront:
Cloudwatch logs only show failures, and show that the server is looking in the right directory for static files.
Succeed:

Request URL
https://dev.jmus.io/test-static/index.html
Request Method
GET
Status Code
200 OK
Remote Address
3.165.160.30:443
Referrer Policy
strict-origin-when-cross-origin
alt-svc
h3=":443"; ma=86400
cache-control
public, max-age=0, s-maxage=31536000
content-encoding
br
content-type
text/html
date
Tue, 28 Oct 2025 19:33:17 GMT
etag
W/"29be2dbc62668fcd27bf3171b6ae56e6"
last-modified
Tue, 28 Oct 2025 14:23:30 GMT
vary
accept-encoding
via
1.1 6a856ba081710dfcff422850619f2dee.cloudfront.net (CloudFront)
x-amz-cf-id
26acCmYDCtvPS4EO1Rl3z737iC_YcG3KTsI6NTyu3dTzdjShggPsow==
x-amz-cf-pop
SEA900-P6
x-cache
Miss from cloudfront
:authority
dev.jmus.io
:method
GET
:path
/test-static/index.html
:scheme
https
accept
text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
accept-encoding
gzip, deflate, br, zstd
accept-language
en-US,en;q=0.9
cache-control
no-cache
pragma
no-cache
priority
u=0, i
sec-ch-ua
"Google Chrome";v="141", "Not?A_Brand";v="8", "Chromium";v="141"
sec-ch-ua-mobile
?0
sec-ch-ua-platform
"Windows"
sec-fetch-dest
document
sec-fetch-mode
navigate
sec-fetch-site
none
sec-fetch-user
?1
upgrade-insecure-requests
1
user-agent
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36
Failed:

Request URL
https://dev.jmus.io/test-static
Request Method
GET
Status Code
502 Bad Gateway
Remote Address
3.165.160.55:443
Referrer Policy
strict-origin-when-cross-origin
alt-svc
h3=":443"; ma=86400
content-length
0
date
Tue, 28 Oct 2025 14:54:48 GMT
via
1.1 7affb0dc1bee1aa20816f896f7e9de7a.cloudfront.net (CloudFront)
x-amplify-status
true
x-amz-cf-id
h8godopFVDjZSwFpVdPkqe27rgSxMTIC6LFPO2_FVcdB3Y9_W0k4NQ==
x-amz-cf-pop
SEA900-P6
x-cache
Error from cloudfront
:authority
dev.jmus.io
:method
GET
:path
/test-static
:scheme
https
accept
text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
accept-encoding
gzip, deflate, br, zstd
accept-language
en-US,en;q=0.9
cache-control
no-cache
pragma
no-cache
priority
u=0, i
sec-ch-ua
"Google Chrome";v="141", "Not?A_Brand";v="8", "Chromium";v="141"
sec-ch-ua-mobile
?0
sec-ch-ua-platform
"Windows"
sec-fetch-dest
document
sec-fetch-mode
navigate
sec-fetch-site
same-origin
sec-fetch-user
?1
upgrade-insecure-requests
1
user-agent
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36
Failure Cloud Watch

<html>
<body>
<!--StartFragment-->
2025-10-28T19:35:41.090Z | Listening on http://localhost:3000 (AWS Amplify Hosting)
-- | --
  | 2025-10-28T19:35:41.097Z | START RequestId: c47e44fe-a343-44f9-a8c6-310a0901f0e0 Version: $LATEST
  | 2025-10-28T19:35:41.098Z | Starting request using compute deployment_id: 3f916a4b-0dec-47e9-b10c-c595a5b9604b and compute version: $LATEST
  | 2025-10-28T19:35:41.114Z | [request error] [unhandled] [GET] https://dev.jmus.io/test-static
  | 2025-10-28T19:35:41.114Z | H3Error: ENOENT: no such file or directory, open '/static/test-static/index.html'
  | 2025-10-28T19:35:41.114Z | at async open (node:internal/fs/promises:639:25)
  | 2025-10-28T19:35:41.114Z | ... 2 lines matching cause stack trace ...
  | 2025-10-28T19:35:41.114Z | at async Server.toNodeHandle (file:///var/task/index.mjs:1983:7) {
  | 2025-10-28T19:35:41.114Z | cause: Error: ENOENT: no such file or directory, open '/static/test-static/index.html'
  | 2025-10-28T19:35:41.114Z | at async open (node:internal/fs/promises:639:25)
  | 2025-10-28T19:35:41.114Z | at async Object.readFile (node:internal/fs/promises:1246:14)
  | 2025-10-28T19:35:41.114Z | at async Object.handler (file:///var/task/index.mjs:1712:19)
  | 2025-10-28T19:35:41.114Z | at async Server.toNodeHandle (file:///var/task/index.mjs:1983:7) {
  | 2025-10-28T19:35:41.114Z | errno: -2,
  | 2025-10-28T19:35:41.114Z | code: 'ENOENT',
  | 2025-10-28T19:35:41.114Z | syscall: 'open',
  | 2025-10-28T19:35:41.114Z | path: '/static/test-static/index.html'
  | 2025-10-28T19:35:41.114Z | },
  | 2025-10-28T19:35:41.114Z | statusCode: 500,
  | 2025-10-28T19:35:41.114Z | fatal: false,
  | 2025-10-28T19:35:41.114Z | unhandled: true,
  | 2025-10-28T19:35:41.114Z | statusMessage: undefined,
  | 2025-10-28T19:35:41.114Z | data: undefined
  | 2025-10-28T19:35:41.114Z | }
  | 2025-10-28T19:35:48.889Z | REPORT RequestId: c47e44fe-a343-44f9-a8c6-310a0901f0e0 Duration: 7790.89 ms Billed Duration: 8035 ms Memory Size: 1024 MB Max Memory Used: 124 MB Init Duration: 244.04 ms
  | 2025-10-28T19:35:57.773Z | START RequestId: 54078951-40ea-41c8-80cb-62742226b780 Version: $LATEST
  | 2025-10-28T19:35:57.774Z | Starting request using compute deployment_id: 3f916a4b-0dec-47e9-b10c-c595a5b9604b and compute version: $LATEST
  | 2025-10-28T19:35:58.087Z | REPORT RequestId: 54078951-40ea-41c8-80cb-62742226b780 Duration: 313.13 ms Billed Duration: 314 ms Memory Size: 1024 MB Max Memory Used: 126 MB

<!--EndFragment-->
</body>
</html>
So what does this tell us:

Static pages are not stored at their typical location when the call hits the server:
 '/static/test-static/index.html'
When you build a nuxt project this is where the static built files are typically stored. When '/test-static/ is redirected in the server to '/static/test-static/index.html the static folder is not there.

When we get /test_tatic/index.htm we load our static asset and we don't produce a log in cloudwatch.
Conclusion:
Static files are not stored in the typical place inside the black box of Amplify Hosting. There is some gateway in front of our server for serving our static files on the CDN. When /test_static/ doesn't match the /test_static/index.html that that gateway is expecting, it falls back to our server where it is routed to the usual static files place on the server, but their not there - amplify built them somewhere for serving in CDN.

Expected behavior

Static prerendered pages should render when fetched at their path.

Reproduction steps

  1. Setup nuxt config. I used Vuetify and eslint. Those aren't neccessary:
export default defineNuxtConfig({
  compatibilityDate: '2025-07-15',
  devtools: { enabled: true },
  modules: [
    vuetify_hook,
    '@nuxt/eslint'
  ],
  nitro: {
    preset: 'aws-amplify',
    logLevel: 5,
    awsAmplify: {
      // Set to true so Lambda doesn't try to serve static files from filesystem
      catchAllStaticFallback: true
    },
    routeRules: {
      '/api/**': { cors: true },
      '/': { ssr: true },
      '/static-test': { prerender: true }
    }
  },
  css: [
    'vuetify/styles',
    '@mdi/font/css/materialdesignicons.css'
  ],
  build: {
    transpile: ['vuetify']
  },
  runtimeConfig: {
    public: {}
  }
})
  1. Create a static test page '/pages/static-test.vue'
  2. Deploy to amplify hosting.
  3. Navigate to /pages/statiic-test.vue and refresh the page.

Code Snippet

// Put your code below this line.

Log output

// Put your logs below this line


aws-exports.js

export default defineNuxtConfig({
compatibilityDate: '2025-07-15',
devtools: { enabled: true },
modules: [
vuetify_hook,
'@nuxt/eslint'
],
nitro: {
preset: 'aws-amplify',
logLevel: 5,
awsAmplify: {
// Set to true so Lambda doesn't try to serve static files from filesystem
catchAllStaticFallback: true
},
routeRules: {
'/api/**': { cors: true },
'/': { ssr: true },
'/static-test': { prerender: true }
}
},
css: [
'vuetify/styles',
'@mdi/font/css/materialdesignicons.css'
],
build: {
transpile: ['vuetify']
},
runtimeConfig: {
public: {}
}
})

```

### Manual configuration

_No response_

### Additional configuration

_No response_

### Mobile Device

_No response_

### Mobile Operating System

_No response_

### Mobile Browser

_No response_

### Mobile Browser Version

_No response_

### Additional information and screenshots

_No response_

Metadata

Metadata

Assignees

No one assigned

    Labels

    Gen 2Issues related to Gen 2 Amplify projectsHostingIssues related to Amplify HostingSSRIssues related to Server Side RenderingVueRelated to Vue Framework issuesbugSomething isn't workingpending-maintainer-responseIssue is pending a response from the Amplify team.

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions