{"record":{"id":"45f5a998ad8e0576","repo":"vercel/next.js","slug":"using-a-self-signed-certificate-is-only-supported","errorCode":null,"errorMessage":"Using a self signed certificate is only supported with `next dev`.","messagePattern":"Using a self signed certificate is only supported with `next dev`\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/next/src/server/lib/start-server.ts","lineNumber":236,"sourceCode":"  }\n  let upgradeHandler: WorkerUpgradeHandler = async (\n    req,\n    socket,\n    head\n  ): Promise<void> => {\n    if (handlersPromise) {\n      await handlersPromise\n      return upgradeHandler(req, socket, head)\n    }\n    throw new Error('Invariant upgrade handler was not setup')\n  }\n\n  let nextServer: NextServer | undefined\n  let devMemoryThresholdRestart = true\n\n  // setup server listener as fast as possible\n  if (selfSignedCertificate && !isDev) {\n    throw new Error(\n      'Using a self signed certificate is only supported with `next dev`.'\n    )\n  }\n\n  async function requestListener(req: IncomingMessage, res: ServerResponse) {\n    try {\n      if (handlersPromise) {\n        await handlersPromise\n        handlersPromise = undefined\n      }\n      await requestHandler(req, res)\n    } catch (err) {\n      res.statusCode = 500\n      res.end('Internal Server Error')\n      Log.error(`Failed to handle request for ${req.url}`)\n      console.error(err)\n    } finally {\n      const memoryRestartStats = getMemoryRestartStats(","sourceCodeStart":218,"sourceCodeEnd":254,"githubUrl":"https://github.com/vercel/next.js/blob/0ae8c72462952df163f1b1e0726641bc5b40dc93/packages/next/src/server/lib/start-server.ts#L218-L254","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: HTTPS config always on\nmodule.exports = {\n  experimental: { https: { selfSigned: true } },\n}\n\n// after: enable only in dev\nmodule.exports = process.env.NODE_ENV === 'development'\n  ? { experimental: { https: { selfSigned: true } } }\n  : {}","handlingStrategy":"validation","validationCode":"const isDev = process.env.NODE_ENV === 'development'\nif (config.experimental?.https && !isDev) {\n  throw new Error('self-signed cert is dev-only; remove it for production')\n}","typeGuard":"function canUseSelfSignedCert(isDev: boolean, config: any): boolean {\n  return !config?.experimental?.https || isDev\n}","tryCatchPattern":"null","preventionTips":["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."],"tags":["https","ssl","dev-server","production"],"analyzedSha":"0ae8c72462952df163f1b1e0726641bc5b40dc93","analyzedAt":"2026-08-06T19:44:29.143Z","schemaVersion":2},"datasetVersion":"2026-08-07T02:17:10.218Z"}