Skip to main content

CloudFront 404 Error Page Configuration

Problem

When accessing a non-existent URL like https://docs.sendsquared.com/docs/bad-url, CloudFront returns an ugly XML error or default error page instead of the Docusaurus-generated 404.html page.

Solution

Step 1: Configure S3 Static Website Hosting

  1. Go to your S3 bucket in AWS Console
  2. Navigate to Properties tab
  3. Scroll to Static website hosting
  4. Click Edit
  5. Configure:
    • Static website hosting: Enable
    • Hosting type: Host a static website
    • Index document: index.html
    • Error document: 404.html
  6. Click Save changes

Step 2: Configure CloudFront Error Pages

  1. Go to CloudFront in AWS Console
  2. Select your distribution
  3. Navigate to Error pages tab
  4. Click Create custom error response

For 404 Errors:

  • HTTP error code: 404: Not Found
  • Customize error response: Yes
  • Response page path: /404.html
  • HTTP response code: 404: Not Found
  • Error caching minimum TTL: 10 (seconds)

For 403 Errors (Important for SPAs):

  • HTTP error code: 403: Forbidden
  • Customize error response: Yes
  • Response page path: /404.html
  • HTTP response code: 404: Not Found
  • Error caching minimum TTL: 10 (seconds)

Step 3: Invalidate CloudFront Cache

After making changes:

aws cloudfront create-invalidation \
--distribution-id YOUR_DISTRIBUTION_ID \
--paths "/*"

Or in AWS Console:

  1. Select your distribution
  2. Go to Invalidations tab
  3. Click Create invalidation
  4. Enter /* in the object paths
  5. Click Create invalidation

Alternative: Using CloudFront Functions

For more advanced routing, you can use CloudFront Functions:

function handler(event) {
var request = event.request;
var uri = request.uri;

// Check if the URI is for a docs page that doesn't have an extension
if (uri.startsWith('/docs/') && !uri.includes('.')) {
// Try to append .html
request.uri = uri + '.html';
}

return request;
}

Testing

After configuration, test these scenarios:

  1. Valid page: https://docs.sendsquared.com/docs/getting-started
  2. Invalid page: https://docs.sendsquared.com/docs/bad-url → Should show custom 404
  3. Root 404: https://docs.sendsquared.com/non-existent → Should show custom 404
  4. Deep 404: https://docs.sendsquared.com/docs/category/fake/page → Should show custom 404

Troubleshooting

404 Page Not Showing

  1. Verify 404.html exists in S3:

    aws s3 ls s3://your-bucket/404.html
  2. Check CloudFront Origin Settings:

    • Origin should point to S3 bucket website endpoint, not the S3 API endpoint
    • Example: your-bucket.s3-website-us-east-1.amazonaws.com
    • NOT: your-bucket.s3.amazonaws.com
  3. Clear Browser Cache:

    • Hard refresh: Cmd+Shift+R (Mac) or Ctrl+Shift+R (Windows)
    • Or test in incognito/private mode

Still Seeing XML Errors

If you're still seeing XML errors like:

<Error>
<Code>NoSuchKey</Code>
<Message>The specified key does not exist.</Message>
</Error>

This means CloudFront is hitting S3's REST API directly. Solutions:

  1. Use S3 Website Endpoint as Origin:

    • Change origin from bucket.s3.amazonaws.com
    • To: bucket.s3-website-region.amazonaws.com
  2. Or Use Origin Access Identity (OAI) with Lambda@Edge:

    • Keep S3 private
    • Use Lambda@Edge to handle 404s
    • More complex but more secure

Docusaurus-Specific Considerations

Build Configuration

Ensure your docusaurus.config.js includes:

module.exports = {
// ... other config
onBrokenLinks: 'warn', // or 'ignore' for production
onBrokenMarkdownLinks: 'warn',

// Ensure trailing slashes are handled consistently
trailingSlash: false, // or true, but be consistent
};

Custom 404 Page (Optional)

While Docusaurus provides a default 404, you can customize it:

  1. Create src/theme/NotFound.js:
import React from 'react';
import Layout from '@theme/Layout';
import Link from '@docusaurus/Link';

export default function NotFound() {
return (
<Layout title="Page Not Found">
<main className="container margin-vert--lg">
<div className="row">
<div className="col col--6 col--offset-3">
<h1 className="hero__title">404 - Page Not Found</h1>
<p>We couldn't find what you're looking for.</p>
<p>
<Link to="/">Return to homepage</Link>
</p>
</div>
</div>
</main>
</Layout>
);
}
  1. Build and deploy:
npm run build
aws s3 sync ./build s3://your-bucket --delete
aws cloudfront create-invalidation --distribution-id YOUR_ID --paths "/*"