remix-run/remix · error · Error
Unsupported tsconfig compilerOptions.jsx = "${jsx}" for ${fi
Error message
Unsupported tsconfig compilerOptions.jsx = "${jsx}" for ${filePath}. remix/node-tsx must compile JSX to runnable JavaScript. What it means
remix/node-tsx compiles TSX files to runnable JavaScript using your tsconfig compilerOptions. The `jsx` option is set to `preserve` (or `react-native`), which leaves JSX syntax in the output instead of transforming it — output Node cannot execute. The transformer refuses to proceed because the compiled result would crash at runtime.
Source
Thrown at packages/node-tsx/src/lib/transform.ts:159
if (value === null) {
return 'null'
}
return typeof value
}
function getJsxTransformOptions(
filePath: string,
compilerOptions?: TsconfigTransformCompilerOptions,
): Pick<TransformOptions, 'jsx'> {
let jsx = compilerOptions?.jsx
let importSource = compilerOptions?.jsxImportSource
let factory = compilerOptions?.jsxFactory
let fragment = compilerOptions?.jsxFragmentFactory
if (jsx === 'preserve' || jsx === 'react-native') {
throw new Error(
`Unsupported tsconfig compilerOptions.jsx = "${jsx}" for ${filePath}. ` +
'remix/node-tsx must compile JSX to runnable JavaScript.',
)
}
if (jsx == null || jsx === 'react-jsx' || jsx === 'react-jsxdev') {
return {
jsx: {
development: jsx === 'react-jsxdev',
importSource,
runtime: 'automatic',
},
}
}
return {
jsx: {
pragma: factory,View on GitHub (pinned to 9696913134)
Solutions
- Set `"jsx": "react-jsx"` (recommended) or `"jsx": "react-jsxdev"`/`"react"` in the tsconfig that applies to the file
- Check `tsconfig.node.json`/extended configs in monorepos for an overriding `jsx: preserve`
- If you intentionally preserve JSX for another bundler, exclude those files from node-tsx loading or use a separate tsconfig for the runtime
Example fix
// before (tsconfig.json)
{ "compilerOptions": { "jsx": "preserve" } }
// after
{ "compilerOptions": { "jsx": "react-jsx" } } Defensive patterns
Strategy: validation
Validate before calling
import fs from 'node:fs'
let tsconfig = JSON.parse(fs.readFileSync('tsconfig.json', 'utf8'))
let jsx = tsconfig.compilerOptions?.jsx
if (jsx === 'preserve' || jsx === 'react-native') {
throw new Error('Fix tsconfig jsx before running under remix/node-tsx')
} Type guard
null
Prevention
- Keep one tsconfig for type-checking (jsx: preserve ok) and ensure the runtime tsconfig uses react-jsx
- Add a CI check that fails on jsx: preserve in the app tsconfig
- Avoid editor auto-generated tsconfigs overriding yours
When it happens
Trigger: A .tsx file is loaded through remix/node-tsx while the effective tsconfig sets `"jsx": "preserve"` or `"jsx": "react-native"`. Can also happen when an editor/IDE auto-generates a tsconfig or when a tool writes jsx: preserve for type-only configs.
Common situations: Teams that keep `jsx: preserve` for a separate bundler pass (Vite/webpack handle JSX) but then run the same files directly under the Remix node-tsx runtime; monorepos where a root tsconfig overrides the app tsconfig; newly scaffolded projects copying a type-check-only tsconfig.
Related errors
- Invalid tsconfig compilerOptions for ${filePath}.\nremix/nod
- Invalid package.json at ${packageJsonPath}. Expected an obje
AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27).
Data as JSON: /api/errors/987ba75e34bcf471.
Report an issue: GitHub.