How to Debug Issues Within the Cypress Server: A Complete Guide

Set the DEBUG=cypress:* environment variable to enable verbose logging, then use Node's --inspect-brk flag to attach a debugger and step through the server lifecycle in packages/server/lib/server-base.ts to isolate port conflicts, proxy failures, or unexpected shutdowns.

The Cypress server (located in packages/server within the cypress-io/cypress repository) orchestrates the HTTP server, file serving, HTTPS proxy, and WebSocket coordination that powers every test run. When you need to debug issues within the Cypress server, you must instrument its TypeScript source code directly, capture event emitter output, and leverage Node.js debugging tools to trace the asynchronous flow from server creation to socket handshake.

Enable Verbose Logging with the DEBUG Environment Variable

The server uses the debug npm package to emit detailed runtime information via namespaces like cypress:server*. When you set the DEBUG environment variable, these messages appear in the console, revealing exactly when the HTTP server is created, when the file server starts, and when the HTTPS proxy is instantiated.

Set the variable to capture all server output:

DEBUG=cypress:* yarn dev

Or narrow the scope to server-specific logs only:

DEBUG=cypress:server* yarn cypress:run

Look for messages containing createServer, ensuring baseUrl, or error on socket to identify where the lifecycle breaks.

Attach Node's Inspector for Step-by-Step Debugging

For failures that logging alone cannot explain, run Cypress with Node's inspector flag to pause execution and attach Chrome DevTools, VS Code, or WebStorm:

node --inspect-brk $(npm bin)/cypress open

Then connect your debugger to ws://127.0.0.1:9229. Set breakpoints inside ServerBase.createServer (around lines 70-90 in packages/server/lib/server-base.ts) to inspect the config.port, config.baseUrl, and the _listen result. If the server crashes during WebSocket upgrades, place a breakpoint in ServerBase.onUpgrade (around line 76) to examine the req, socket, and head objects.

Instrument Key Source Files

Knowing where to place console.log statements or breakpoints requires familiarity with three core files that manage the server lifecycle.

Server Lifecycle in server-base.ts

The packages/server/lib/server-base.ts file contains the ServerBase class, which is the primary orchestrator. Key methods include:

  • ServerBase.createServer – Instantiates the HTTP server, file server, and HTTPS proxy (lines 70-90).
  • ServerBase.onUpgrade – Handles WebSocket upgrade events (line 76).
  • setupCrossOriginRequestHandling – Emits error and warning events via this._eventBus.

When debugging proxy-related issues, examine the HTTPS proxy creation at lines 94-98 and the onRequest / onUpgrade callbacks. The proxy logs are emitted via debug('proxy request…') in packages/server/lib/https-proxy.ts.

Project Management in project-base.ts

The packages/server/lib/project-base.ts file creates a ServerBase instance for each project and wires up lifecycle events. Use ProjectBase.open to trace server initialization and ProjectBase.reset to force a clean shutdown and recreation of the environment, clearing sockets and avoiding state leakage between runs.

Configuration Resolution in config.ts

The server reads its final configuration from cfg in packages/server/lib/config.ts. After ProjectBase.open resolves, log the final config to verify port, proxyUrl, baseUrl, fileServerFolder, and socketIoCookie values:

console.log('Final server config:', cfg)

Capture Server Events and Configuration State

The server exposes an EventEmitter via this._eventBus. You can listen to error and warning events programmatically to capture stack traces that would otherwise be lost:

import { ProjectBase } from '@packages/server/lib/project-base'

const project = new ProjectBase({
  projectRoot: process.cwd(),
  options: { onError: console.error, onWarning: console.warn },
  testingType: 'e2e',
})

project.on('error', (err) => console.error('Server error:', err))
project.on('warning', (warn) => console.warn('Server warning:', warn))

await project.open()

This approach is particularly useful when onError or onWarning callbacks are not provided through the standard CLI interface.

Run Tests in Headed Mode to Capture Runtime Errors

When a test fails because the server crashed, run Cypress with the --headed flag to keep the Electron or Chrome DevTools console open:

yarn cypress:run -- --headed --spec path/to/failing.spec.ts

A headed run displays the runner process console, including server debug output and network-proxy errors that are hidden in CI logs.

Leverage Unit Tests for Reproduction Scenarios

The test suite under packages/server/test/unit/ mirrors the production code and demonstrates expected lifecycle behavior. Key files include:

Replicating a failing test locally can isolate whether the issue stems from your configuration or the server internals.

Practical Debugging Script

Create a temporary script (e.g., debug-server.ts in the repo root) to programmatically start the server and attach event listeners:

import { ProjectBase } from '@packages/server/lib/project-base'
import { config } from '@packages/server/lib/config'

async function main () {
  const cfg = await config.readAndValidate({ /* …options … */ })
  const project = new ProjectBase({
    projectRoot: process.cwd(),
    options: { onError: console.error, onWarning: console.warn },
    testingType: 'e2e',
  })

  project.on('error', err => console.error('⚠️ Server error →', err))
  project.on('warning', warn => console.warn('🔔 Server warning →', warn))

  await project.open()
  
  console.log('🚀 Server listening on port', project.server?.address()?.port)
  
  // Keep the process alive for manual inspection
  await new Promise(() => {})
}

main().catch(err => console.error(err))

Run this with the inspector to step through the entire initialization flow:

node --inspect-brk debug-server.ts

Summary

  • Use DEBUG=cypress:* to surface verbose logs from the debug package in packages/server/lib/server-base.ts.
  • Attach Node's --inspect-brk to step through ServerBase.createServer and inspect config.port, this._httpsProxy, and this._remoteStates.
  • Listen to error and warning events on ProjectBase instances to capture stack traces from this._eventBus.
  • Check packages/server/lib/config.ts to verify final values for port, baseUrl, and proxyUrl after resolution.
  • Call project.reset() to guarantee a clean state between debugging iterations.
  • Reference server-base_spec.ts to understand expected server behavior and edge-case handling.

Frequently Asked Questions

Set the DEBUG environment variable to cypress:server* instead of cypress:*. This namespace filters the output to only messages from packages/server, hiding browser driver logs and runner noise while preserving the HTTP server, proxy, and socket initialization logs.

Which source file contains the main HTTP server creation logic?

The packages/server/lib/server-base.ts file contains the ServerBase class and its createServer method (around lines 70-90), which orchestrates the HTTP server, file server, HTTPS proxy, and GraphQL WebSocket instantiation. This is the primary entry point for server lifecycle debugging.

How can I programmatically reset the server state during debugging?

Call await project.reset() on your ProjectBase instance. According to the source in packages/server/lib/project-base.ts, this method shuts down the current server, clears sockets, and re-creates the environment, preventing state leakage between test runs while you iterate on a fix.

Enable DEBUG=cypress:server* and set breakpoints in packages/server/lib/server-base.ts around lines 94-98 where the HTTPS proxy is created, and in packages/server/lib/https-proxy.ts where debug('proxy request…') is called. Inspect the onRequest and onUpgrade callbacks to see the exact request headers and TLS termination behavior.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →