Fix TypeError: Cannot read properties of undefined (reading 'split') in Express
This error occurs when code tries to access or parse req.cookies before the cookie-parser middleware is registered, leaving req.cookies undefined. The .split() call fails because it is called on undefined. Fix it by ensuring cookie-parser is registered before any route that accesses req.cookies.
Reading the Stack Trace
Here's what each line means:
- at parsePreferences (/app/src/middleware/preferences.js:6:38): The preferences middleware at line 6 tries to read req.cookies.preferences and call .split() on it, but req.cookies is undefined.
- at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5): Express is executing the middleware layer chain; cookie-parser has not run yet because it was registered after this middleware.
- at expressInit (/app/node_modules/express/lib/middleware/init.js:40:5): Express initialization ran but cookie-parser was not yet in the middleware chain at this point.
Common Causes
1. cookie-parser registered after routes
The cookie-parser middleware is added after route handlers, so req.cookies is not populated when routes execute.
const express = require('express');
const cookieParser = require('cookie-parser');
const app = express();
app.get('/preferences', (req, res) => {
const prefs = req.cookies.preferences.split(',');
res.json({ preferences: prefs });
});
// Registered AFTER the route
app.use(cookieParser());
2. Cookie not set by client
The cookie-parser is registered but the specific cookie does not exist on the request, so req.cookies.preferences is undefined.
app.get('/preferences', (req, res) => {
// No guard — assumes cookie always exists
const prefs = req.cookies.preferences.split(',');
res.json({ preferences: prefs });
});
3. Missing cookie-parser dependency
The cookie-parser package is not installed, so the middleware is never registered and req.cookies remains undefined.
// package.json missing cookie-parser
const cookieParser = require('cookie-parser'); // MODULE_NOT_FOUND
The Fix
Move cookie-parser registration above route definitions so req.cookies is populated. Also add a guard to handle the case where the specific cookie does not exist, returning a default empty array instead of crashing.
const express = require('express');
const cookieParser = require('cookie-parser');
const app = express();
app.get('/preferences', (req, res) => {
const prefs = req.cookies.preferences.split(',');
res.json({ preferences: prefs });
});
app.use(cookieParser());
app.listen(3000);
const express = require('express');
const cookieParser = require('cookie-parser');
const app = express();
// cookie-parser BEFORE routes
app.use(cookieParser());
app.get('/preferences', (req, res) => {
const raw = req.cookies?.preferences;
if (!raw) {
return res.json({ preferences: [] });
}
const prefs = raw.split(',');
res.json({ preferences: prefs });
});
app.listen(3000);
Testing the Fix
const request = require('supertest');
const express = require('express');
const cookieParser = require('cookie-parser');
function createApp() {
const app = express();
app.use(cookieParser());
app.get('/preferences', (req, res) => {
const raw = req.cookies?.preferences;
if (!raw) return res.json({ preferences: [] });
res.json({ preferences: raw.split(',') });
});
return app;
}
describe('GET /preferences', () => {
it('returns empty array when no cookie is set', async () => {
const res = await request(createApp()).get('/preferences');
expect(res.status).toBe(200);
expect(res.body.preferences).toEqual([]);
});
it('parses preferences cookie correctly', async () => {
const res = await request(createApp())
.get('/preferences')
.set('Cookie', 'preferences=dark,compact,notifications');
expect(res.status).toBe(200);
expect(res.body.preferences).toEqual(['dark', 'compact', 'notifications']);
});
});
Run your tests:
npx jest --testPathPattern=cookie-parser
Pushing Through CI/CD
git checkout -b fix/express-cookie-parser-error,git add src/app.js src/__tests__/cookieParser.test.js,git commit -m "fix: register cookie-parser before routes and guard cookie access",git push origin fix/express-cookie-parser-error
Your CI config should look something like this:
name: CI
on:
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npx jest --coverage
- run: npm run lint
The Full Manual Process: 18 Steps
Here's every step you just went through to fix this one bug:
- Notice the error alert or see it in your monitoring tool
- Open the error dashboard and read the stack trace
- Identify the file and line number from the stack trace
- Open your IDE and navigate to the file
- Read the surrounding code to understand context
- Reproduce the error locally
- Identify the root cause
- Write the fix
- Run the test suite locally
- Fix any failing tests
- Write new tests covering the edge case
- Run the full test suite again
- Create a new git branch
- Commit and push your changes
- Open a pull request
- Wait for code review
- Merge and deploy to production
- Monitor production to confirm the error is resolved
Total time: 30-60 minutes. For one bug.
Or Let bugstack Fix It in Under 2 minutes
Every step above? bugstack does it automatically.
Step 1: Install the SDK
npm install bugstack-sdk
Step 2: Initialize
const { initBugStack } = require('bugstack-sdk')
initBugStack({ apiKey: process.env.BUGSTACK_API_KEY })
Step 3: There is no step 3.
bugstack handles everything from here:
- Captures the stack trace and request context
- Pulls the relevant source files from your GitHub repo
- Analyzes the error and understands the code context
- Generates a minimal, verified fix
- Runs your existing test suite
- Pushes through your CI/CD pipeline
- Deploys to production (or opens a PR for review)
Time from error to fix deployed: Under 2 minutes.
Human involvement: zero.
Try bugstack Free →No credit card. 5-minute setup. Cancel anytime.
Deploying the Fix (Manual Path)
- Run the test suite locally to confirm cookie parsing works with and without cookies.
- Open a pull request with the middleware reorder and guard clause.
- Wait for CI checks to pass on the PR.
- Have a teammate review and approve the PR.
- Merge to main and verify cookie-dependent features in staging before promoting to production.
Frequently Asked Questions
BugStack tests requests with and without cookies, verifies correct parsing and default fallback behavior, and confirms no cookie-dependent routes are broken before marking it safe.
Every fix is delivered as a pull request with full CI validation. Your team reviews and approves before anything reaches production.
Not necessarily. express-session manages its own session cookie internally. You only need cookie-parser if you read other custom cookies via req.cookies in your application code.
Yes, for any cookie containing sensitive data. Pass a secret to cookieParser('my-secret') and use res.cookie('name', value, { signed: true }). Access them via req.signedCookies instead of req.cookies.