Skip to content

Conversation

@aheissenberger
Copy link
Contributor

Source Map Support for Production Error Stack Traces

Overview

This implementation adds support for converting production error stack traces back to their original source locations using source maps. When you build with the --sourcemap flag, error messages in production will show the original file locations and line numbers instead of the compiled/bundled locations.

How It Works

1. Source Map Detection

When the server starts in production mode, it checks if source map files (.map) exist alongside the built files in the output directory (default: .react-server/server/). If found, the SOURCEMAP_ENABLED flag is set in the runtime context.

File: lib/start/ssr-handler.mjs

  • Checks for .map files during initialization
  • Sets the SOURCEMAP_ENABLED runtime flag

2. Stack Trace Conversion

The source-map-support package is dynamically imported and installed at server startup when source maps are detected. It automatically hooks into Node.js's Error.prepareStackTrace to convert stack traces:

Package: source-map-support (dynamically loaded)

  • Only imported when .map files are detected
  • Automatically loads .map files from the file system
  • Caches parsed source maps for performance
  • Hooks into Node.js error handling
  • Transparently converts all stack traces system-wide

3. Error Logging Integration

Once source-map-support is installed, all errors throughout the application automatically have their stack traces converted. No manual conversion is needed at individual error points.

Files Modified:

  • lib/start/ssr-handler.mjs - Installs source-map-support at startup

Usage

Building with Source Maps

# Build with separate source map files
npx react-server build --sourcemap

# Build with inline source maps
npx react-server build --sourcemap inline

# Build with hidden source maps (not referenced in code)
npx react-server build --sourcemap hidden

Starting the Production Server

npx react-server start

The server will automatically detect if source maps are available and use them for error reporting.

Example

Without Source Maps

Error: Something went wrong
    at /app/.react-server/server/index.mjs:1234:56
    at /app/.react-server/server/render.mjs:789:12

With Source Maps

Error: Something went wrong
    at /app/src/components/MyComponent.jsx:45:23
    at /app/src/pages/index.jsx:12:8

Implementation Details

Modified Files

  1. server/symbols.mjs

    • Added SOURCEMAP_ENABLED symbol for runtime flag
  2. lib/start/ssr-handler.mjs

    • Detects source map availability on startup (checks for .map files)
    • Dynamically imports source-map-support only when source maps are detected
    • Sets SOURCEMAP_ENABLED runtime flag
    • Installs source-map-support when source maps are available

Dependencies Added

  • source-map-support - Automatically converts stack traces using source maps (dynamically loaded only when needed)

Performance Considerations

  • Dynamic Loading: source-map-support is only imported when source maps are detected, reducing memory footprint in development and when source maps aren't available
  • One-time Check: Source map detection happens once at server startup, not on every request
  • Efficient Caching: source-map-support caches parsed source maps in memory after first load
  • Minimal Overhead: Hooks are installed once at startup with negligible performance impact
  • Graceful Fallback: Falls back to original stack trace if source map lookup fails

Conditional Execution

The source map conversion only happens when:

  1. The build was created with --sourcemap flag
  2. The .map files exist in the output directory
  3. Running in production mode (not dev mode)
  4. An error occurs

Notes

  • Dev mode already has source map support through Vite's module graph
  • This implementation is specifically for production builds
  • Source maps should be kept secure and not deployed to public-facing servers if they contain sensitive information
  • The --sourcemap hidden option generates source maps but doesn't reference them in the code (useful for error tracking without exposing sources)

Copilot AI review requested due to automatic review settings November 14, 2025 09:18
Copilot finished reviewing on behalf of aheissenberger November 14, 2025 09:22
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This pull request adds source map support for production error stack traces by dynamically loading and installing the source-map-support package when .map files are detected at server startup. This allows production errors to display original source locations instead of compiled bundle locations.

Key Changes

  • Added SOURCEMAP_ENABLED runtime flag to track source map availability
  • Implemented source map detection by checking for .map files in the build output directory
  • Dynamically imports and installs source-map-support only when source maps are present

Reviewed Changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
pnpm-lock.yaml Added [email protected] dependency and updated peer dependency resolution for various packages
packages/react-server/server/symbols.mjs Added new SOURCEMAP_ENABLED symbol for runtime flag tracking
packages/react-server/package.json Added source-map-support dependency specification
packages/react-server/lib/start/ssr-handler.mjs Implemented source map detection logic and dynamic loading of source-map-support at server startup
packages/react-server/lib/start/action.mjs Added default initialization of SOURCEMAP_ENABLED flag in worker function
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@lazarv
Copy link
Owner

lazarv commented Nov 15, 2025

Hi @aheissenberger!

This is so nice to have finally, and sourcemap handling has been a missing feature for more than 2 years now! I totally forgot to add this to the production server.

I made some suggested changes in review/sourcemap-error.

The most prominent change I would suggest is to use the entry module code and check for the sourceMappingURL line to support inline sourcemaps, and not load the source-map-support module for hidden sourcemaps.

Also, I would rename SOURCEMAP_ENABLED to SOURCEMAP_SUPPORT as this is the name of the feature, and enabled/disabled is its value.

@aheissenberger
Copy link
Contributor Author

When switching to source map detection by checking for the url, the hidden source maps will break.

Have a look at my latest changes which require less code changes and no runtime detection:

  1. create a build meta file which allows to access build settings like source map options at runtime
  2. packages/react-server/server/render-rsc.jsx - fix missing stack trace in server log from react server components in production. Without this fix the server log logs the same anonymous message as shown on the client An error occurred in the Server Components render. The specific message is omitted in production ...

I tested the rsc component by adding a throw error to function allTodos(), it worked very well in production including mapping to the right source position. But the already existing stack trace in dev mode does not provide the correct line number - see #285

@aheissenberger
Copy link
Contributor Author

aheissenberger commented Nov 17, 2025

maybe using the cli option --enable-source-maps and adding some infos to the docs is the best way to go since this option exists since node 12.12.0

NODE_OPTIONS='--enable-source-maps' react-server start

import { ServerFunctionNotFoundError } from "./action-state.mjs";
import { cwd } from "../lib/sys.mjs";

/**
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This wrapper could be moved to https://github.com/lazarv/react-server/blob/main/packages/react-server/lib/start/create-logger.mjs, so that the logger would use this everywhere by default. Also, the wrapper should only be enabled when using source maps.


// Write build metadata with sourcemap option
await writeFile(
join(cwd, options.outDir, "server/build-meta.json"),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As all other manifests have the server/<type>-manifest.json name, I would suggest to have this also named server/build-manifest.json.

const moduleCacheStorage = new ContextManager();
await module_loader_init$(moduleLoader, moduleCacheStorage);

if (buildMetadata.sourcemap && buildMetadata.sourcemap !== false) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As this is now related to manifests, I would move this into https://github.com/lazarv/react-server/blob/main/packages/react-server/lib/start/manifest.mjs#L52-L56 and also store it in the context.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants