vercel/next.js · error · Error
Using a self signed certificate is only supported with `next
Error message
Using a self signed certificate is only supported with `next dev`.
What it means
Thrown by start-server when the experimental self-signed HTTPS certificate option is enabled but the server is not in development mode. Self-signed certificate generation is a dev-only convenience and is intentionally blocked for production starts.
Source
Thrown at packages/next/src/server/lib/start-server.ts:236
}
let upgradeHandler: WorkerUpgradeHandler = async (
req,
socket,
head
): Promise<void> => {
if (handlersPromise) {
await handlersPromise
return upgradeHandler(req, socket, head)
}
throw new Error('Invariant upgrade handler was not setup')
}
let nextServer: NextServer | undefined
let devMemoryThresholdRestart = true
// setup server listener as fast as possible
if (selfSignedCertificate && !isDev) {
throw new Error(
'Using a self signed certificate is only supported with `next dev`.'
)
}
async function requestListener(req: IncomingMessage, res: ServerResponse) {
try {
if (handlersPromise) {
await handlersPromise
handlersPromise = undefined
}
await requestHandler(req, res)
} catch (err) {
res.statusCode = 500
res.end('Internal Server Error')
Log.error(`Failed to handle request for ${req.url}`)
console.error(err)
} finally {
const memoryRestartStats = getMemoryRestartStats(View on GitHub (pinned to 0ae8c72462)
Solutions
- Use `next dev` when you need the self-signed certificate feature.
- Remove or guard the experimental.https/selfSignedCertificate config for production builds.
- For production HTTPS, terminate TLS at a reverse proxy/load balancer with a real certificate instead.
Example fix
// before: HTTPS config always on
module.exports = {
experimental: { https: { selfSigned: true } },
}
// after: enable only in dev
module.exports = process.env.NODE_ENV === 'development'
? { experimental: { https: { selfSigned: true } } }
: {} Defensive patterns
Strategy: validation
Validate before calling
const isDev = process.env.NODE_ENV === 'development'
if (config.experimental?.https && !isDev) {
throw new Error('self-signed cert is dev-only; remove it for production')
} Type guard
function canUseSelfSignedCert(isDev: boolean, config: any): boolean {
return !config?.experimental?.https || isDev
} Try / catch
null
Prevention
- Gate experimental.https behind a NODE_ENV check in next.config.js.
- Use a real certificate + reverse proxy for production HTTPS.
- Don't deploy dev-only config to production.
When it happens
Trigger: next.config.js enables experimental.https (or selfSignedCertificate) and the app is started with `next start` (production) instead of `next dev`. The guard `if (selfSignedCertificate && !isDev)` triggers.
Common situations: Keeping the dev HTTPS config in next.config.js when deploying, or a custom server script that calls startServer with isDev:false while the config still requests HTTPS.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- Dev server did not become ready within ${timeoutMs}ms
- hmrRefresh can only be used in development mode. Please use
- Failed to fetch _devPagesManifest.json. Is something blockin
- Failed to read file contents of ${filename}.
- Failed to parse source map URL for ${filename}.
AI-assisted analysis of vercel/next.js@0ae8c72462 (2026-08-06).
Data as JSON: /api/errors/45f5a998ad8e0576.
Report an issue: GitHub.