How to Fix: Error [TypeError]: Cannot read properties of undefined (reading ‘substring’)
That substring crash is usually a missing environment variable, not a MongoDB problem.
In this Dossier issue, the server starts only after you provide a MongoDB URI and Google OAuth credentials, but it fails with Error [TypeError]: Cannot read properties of undefined (reading ‘substring’). That message is a strong sign that some code expects a string from process.env, but receives undefined instead. When the app later calls .substring() on that missing value, Node.js throws immediately.
Table of Contents
Understanding the Root Cause
This error happens when code similar to the following runs:
const secret = process.env.GOOGLE_CLIENT_SECRET.substring(0, 5);
If process.env.GOOGLE_CLIENT_SECRET is missing, empty, misspelled, or not loaded at runtime, the value is undefined. JavaScript strings support substring(), but undefined does not, so the app crashes.
In apps like Dossier, this usually happens in one of these places:
- NextAuth or OAuth provider configuration
- JWT or app secret generation logic
- MongoDB connection helpers that inspect or trim a URI
- Custom startup code that assumes env values always exist
The issue is rarely the substring call itself. The real root cause is that a required environment variable was never loaded, was named incorrectly, or is being accessed before configuration initialization completes.
Step-by-Step Solution
The fix is to identify which env variable is undefined, validate it early, and fail with a clear error before calling string methods on it.
1. Verify your environment file
Check that your project has the expected variables in the correct file, typically .env.local, .env, or another runtime-specific env file used by the app.
MONGODB_URI=mongodb+srv://username:password@cluster.mongodb.net/dossier?retryWrites=true&w=majority
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
NEXTAUTH_SECRET=your_random_long_secret
NEXTAUTH_URL=http://localhost:3000
Important checks:
- No extra spaces around the =
- No quotes unless the app explicitly expects them
- No misspelled keys such as GOOGLE_SECRET instead of GOOGLE_CLIENT_SECRET
- The server was restarted after editing env files
2. Inspect the configuration code that uses substring
Search the repository for substring( and inspect all env-related usage.
grep -R "substring(" .
Also inspect direct env access:
grep -R "process.env" .
You are looking for code patterns like:
process.env.SOME_KEY.substring(...)
process.env.SOME_KEY.slice(...)
const value = process.env.SOME_KEY
value.substring(...)
In this issue, the crash most likely comes from an OAuth, auth secret, or connection setup path triggered during server startup.
3. Add a safe env validator
Instead of trusting process.env, validate all required variables up front.
function requireEnv(name) {
const value = process.env[name];
if (!value || !value.trim()) {
throw new Error(`Missing required environment variable: ${name}`);
}
return value;
}
const MONGODB_URI = requireEnv('MONGODB_URI');
const GOOGLE_CLIENT_ID = requireEnv('GOOGLE_CLIENT_ID');
const GOOGLE_CLIENT_SECRET = requireEnv('GOOGLE_CLIENT_SECRET');
const NEXTAUTH_SECRET = requireEnv('NEXTAUTH_SECRET');
This converts a vague runtime failure into a precise startup error.
4. Replace unsafe substring usage
If the code currently assumes the env value always exists, change it.
Unsafe:
const shortSecret = process.env.GOOGLE_CLIENT_SECRET.substring(0, 6);
Safe:
const googleClientSecret = requireEnv('GOOGLE_CLIENT_SECRET');
const shortSecret = googleClientSecret.substring(0, 6);
Or, if the value is optional, guard it explicitly:
const shortSecret = process.env.GOOGLE_CLIENT_SECRET
? process.env.GOOGLE_CLIENT_SECRET.substring(0, 6)
: '';
Use the guarded version only for truly optional values. For authentication settings, required validation is better.
5. Check auth configuration
If this repo uses Google login, inspect the provider setup. It often looks like this:
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
})
Make it explicit and validated:
const googleClientId = requireEnv('GOOGLE_CLIENT_ID');
const googleClientSecret = requireEnv('GOOGLE_CLIENT_SECRET');
GoogleProvider({
clientId: googleClientId,
clientSecret: googleClientSecret,
})
If the application also uses NEXTAUTH_SECRET or another app secret, validate that too before startup.
6. Check MongoDB connection setup
Some projects manipulate the URI before connecting, such as masking it in logs or extracting a database name. If the URI is missing, any string operation can fail.
const mongoUri = requireEnv('MONGODB_URI');
import mongoose from 'mongoose';
export async function connectDB() {
await mongoose.connect(mongoUri);
}
Avoid logic like this unless the value is guaranteed:
const dbName = process.env.MONGODB_URI.substring(process.env.MONGODB_URI.lastIndexOf('/') + 1);
If you need parsing, validate first.
7. Restart the server completely
After updating env files, stop the process and start it again. Many frameworks do not fully reload new environment values during hot refresh.
npm run dev
or
yarn dev
8. Add a startup diagnostic temporarily
If the failing variable is still unclear, log only whether required keys exist, never full secret values.
console.log('MONGODB_URI loaded:', !!process.env.MONGODB_URI);
console.log('GOOGLE_CLIENT_ID loaded:', !!process.env.GOOGLE_CLIENT_ID);
console.log('GOOGLE_CLIENT_SECRET loaded:', !!process.env.GOOGLE_CLIENT_SECRET);
console.log('NEXTAUTH_SECRET loaded:', !!process.env.NEXTAUTH_SECRET);
This helps isolate the missing key without leaking credentials.
9. Use a dedicated env module
A clean long-term fix is to centralize all configuration.
export function requireEnv(name) {
const value = process.env[name];
if (!value || !value.trim()) {
throw new Error(`Missing required environment variable: ${name}`);
}
return value;
}
export const env = {
mongodbUri: requireEnv('MONGODB_URI'),
googleClientId: requireEnv('GOOGLE_CLIENT_ID'),
googleClientSecret: requireEnv('GOOGLE_CLIENT_SECRET'),
nextAuthSecret: requireEnv('NEXTAUTH_SECRET'),
};
Then use it everywhere:
import { env } from './env';
console.log(env.mongodbUri);
console.log(env.googleClientId);
10. Confirm correct values from project docs
If the repository has setup instructions, compare your local env keys with the exact variable names expected by the codebase. Review the project source on the Dossier repository and align your env file with the implementation, not assumptions.
Common Edge Cases
- Wrong env file name: The app may load .env.local but you edited .env, or vice versa.
- Server not restarted: The env file was fixed, but the old process still runs with stale variables.
- Different runtime context: A variable is available on the client build but not the server runtime, or the reverse.
- Misspelled keys: GOOGLE_SECRET, GOOGLE_ID, or MONGO_URI may not match the names used in code.
- Empty string values: A key exists but is blank, which is still invalid for auth and database configuration.
- Quotes or copy-paste issues: Extra quotes, hidden spaces, or line breaks can break parsing.
- OAuth credentials created for the wrong callback URL: The app may progress further after fixing substring, then fail in Google auth because the redirect URI is not configured correctly.
- Missing auth secret: Even if Google credentials are present, missing NEXTAUTH_SECRET or equivalent can trigger startup failures in adjacent config code.
FAQ
1. Why does the error mention substring instead of the missing env variable?
Because JavaScript throws at the exact operation that failed. The runtime only knows that undefined.substring(…) was attempted. It does not automatically tell you that the undefined value originally came from process.env.
2. I already added MongoDB and Google credentials. Why am I still seeing the error?
One of the following is still likely true: the variable name does not match the code, the env file is not being loaded, the server was not restarted, or another required variable such as NEXTAUTH_SECRET is also missing.
3. What is the best permanent fix for this issue?
Create a single configuration module that validates every required environment variable at startup. Then import validated values everywhere instead of reading raw process.env throughout the app.
Once you validate env values early, this class of startup bug becomes much easier to diagnose, and the vague Cannot read properties of undefined error is replaced by a clear, actionable configuration message.