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– Emitserrorandwarningevents viathis._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:
packages/server/test/unit/server-base_spec.ts– Shows how the server handles upgrades and HTTP/HTTPS proxy behavior.packages/server/test/unit/project-base_spec.ts– Demonstrates opening, resetting, and closing aProjectBaseinstance.
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 thedebugpackage inpackages/server/lib/server-base.ts. - Attach Node's
--inspect-brkto step throughServerBase.createServerand inspectconfig.port,this._httpsProxy, andthis._remoteStates. - Listen to
errorandwarningevents onProjectBaseinstances to capture stack traces fromthis._eventBus. - Check
packages/server/lib/config.tsto verify final values forport,baseUrl, andproxyUrlafter resolution. - Call
project.reset()to guarantee a clean state between debugging iterations. - Reference
server-base_spec.tsto understand expected server behavior and edge-case handling.
Frequently Asked Questions
How do I filter debug output to show only server-related messages?
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.
What is the recommended way to debug proxy errors in the Cypress server?
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →