✨ Strapi MCP is now Generally Available - let your agents manage your Strapi content ✨

EcosystemIntermediate6 min read

"Cannot destructure property 'client' of 'db.config.connection'" in Strapi

September 9, 2026
"Cannot destructure property 'client' of 'db.config.connection'" in Strapi

Strapi refuses to boot:

debug: ⛔️ Server wasn't able to start properly.
error: Cannot destructure property 'client' of 'db.config.connection' as it is undefined.
TypeError: Cannot destructure property 'client' of 'db.config.connection' as it is undefined.
    at getDialect (.../@strapi/database/dist/index.js)
    at new Database (...)
    at Strapi.bootstrap (...)

What it means

Strapi is trying to read client ('postgres', 'mysql', 'sqlite') from your database configuration in order to pick a dialect. It got undefined for the whole connection object.

This is not a wrong password, an unreachable host, or a firewall. Strapi loaded no database configuration at all. Either config/database was not found, or it was found and produced nothing usable.

Once you frame it that way, the search space is small.

Confirm it in one step

Add a log at the very top of the config file:

console.log('>>> config/database loaded');

export default ({ env }) => ({
  connection: {
    client: env('DATABASE_CLIENT', 'postgres'),
    connection: {
      host: env('DATABASE_HOST', '127.0.0.1'),
      port: env.int('DATABASE_PORT', 5432),
      database: env('DATABASE_NAME', 'strapi'),
      user: env('DATABASE_USERNAME', 'strapi'),
      password: env('DATABASE_PASSWORD'),
      ssl: env.bool('DATABASE_SSL', false),
    },
  },
});

If >>> config/database loaded never appears in the logs, the file is not being loaded, so go to causes 1 to 4. If it does appear and the error still fires, the file loaded but returned the wrong shape, so go to cause 5.

Cause 1: TypeScript compiled nothing (noEmit)

The most common cause on TypeScript projects, and the one that resolved the original forum thread.

Strapi builds a TypeScript project by compiling config/, src/, and friends into dist/. If your tsconfig.json contains:

{
  "compilerOptions": {
    "noEmit": true
  }
}

…then tsc type-checks and writes no output. The build appears to succeed. dist/ has no config/database.js. Strapi starts, finds nothing, and throws.

{
  "extends": "@strapi/typescript-utils/tsconfigs/server",
  "compilerOptions": {
    "outDir": "dist",
    "rootDir": "."
    // no "noEmit"
  },
  "include": ["./", "src/**/*.json"],
  "exclude": ["node_modules/", "build/", "dist/", ".cache/", ".tmp/", "src/admin/", "**/*.test.ts", "src/plugins/**"]
}

noEmit: true usually arrives by copying a frontend tsconfig.json, or by a well-meaning editor suggestion. Remove it and rebuild.

Verify:

npm run build
ls -la dist/config/
# database.js must be there

Cause 2: The file is not in the container

The Docker version of the same problem. Your Dockerfile copies the wrong path, so config/ never makes it into the image:

# Build context is the repo root, but the app lives in ./backend
COPY . .            # ← copies the repo root, not the app
COPY ./backend .    # ← correct for that layout

Check inside the running container rather than guessing:

docker compose exec strapi ls -la /opt/app/config/
docker compose exec strapi ls -la /opt/app/dist/config/

Also check .dockerignore. A broad pattern can exclude config/ or tsconfig.json without anyone noticing:

node_modules
.git
.env
# make sure nothing here matches config/ or tsconfig.json

tsconfig.json must be in the image if you build inside it. Without it, tsc falls back to defaults, output lands in unexpected places, and you get this error.

Cause 3: An environment-specific config that returns nothing

config/env/<NODE_ENV>/database.ts completely replaces the base config/database.ts when that NODE_ENV is active; it is not merged.

So a production override that is empty, malformed, or returns a different shape leaves you with no database config in production while development works perfectly.

ls -la config/env/*/
cat config/env/production/database.* 2>/dev/null

If the file exists, make sure it returns the full object, not a partial one:

export default ({ env }) => ({
  connection: {
    client: 'postgres',
    connection: {
      connectionString: env('DATABASE_URL'),
      ssl: { rejectUnauthorized: false },
    },
    debug: false,
  },
});

Note that this file is only loaded when NODE_ENV=production. If your platform sets NODE_ENV=prod or leaves it unset, the folder is ignored and you fall back to the base config, which may itself be fine, or may be the SQLite default.

Cause 4: Running from the wrong directory, or the wrong entry point

Strapi resolves config/ relative to the application root. Starting the process from elsewhere, or pointing a process manager at the wrong cwd, breaks that resolution.

module.exports = {
  apps: [{
    name: 'strapi',
    cwd: '/var/www/strapi',   // must be the project root
    script: 'npm',
    args: 'run start',
  }],
};

For TypeScript projects started programmatically, the factory needs distDir:

const strapi = require('@strapi/strapi');
strapi.createStrapi({ distDir: './dist' }).start();

Without distDir, the process looks for configuration in the source tree at runtime, finds .ts files it cannot execute, and loads nothing. This is a frequent cPanel and shared-hosting failure, because those environments start Node through a wrapper whose working directory is not what you expect.

Cause 5: The config file returns the wrong shape

Less common, but it happens after refactors. Strapi expects the exported function to return an object with a connection key:

// Correct
export default ({ env }) => ({
  connection: {
    client: 'postgres',
    connection: { /* host, port, ... */ },
  },
});

// Wrong: missing the outer `connection` wrapper
export default ({ env }) => ({
  client: 'postgres',
  connection: { /* ... */ },
});

// Wrong: exports the object instead of a function returning it
export default {
  connection: { client: 'postgres', connection: {} },
};

Note the deliberate double nesting: connection.connection. The outer one is Knex's configuration; the inner one is the connection parameters. It reads oddly and it is correct.

Also watch for a stray module.exports in a .ts file, or export default in a .js file where the project expects CommonJS. A module system mismatch means the export is undefined and Strapi sees an empty config.

Diagnostic sequence

# 1. Does the source file exist and is it valid?
ls -la config/database.*
npx tsc --noEmit -p tsconfig.json      # type errors only, no output

# 2. Did the build emit it?
npm run build
ls -la dist/config/

# 3. In a container, is it actually there?
docker compose exec strapi ls -la /opt/app/dist/config/

# 4. Which NODE_ENV is active, and is there an override?
docker compose exec strapi printenv NODE_ENV
ls -la config/env/

# 5. Is the process running from the right directory?
pm2 describe strapi | grep -i "exec cwd"
ErrorMeaning
Cannot destructure property 'client'Config file did not load at all
SASL: ... client password must be a stringConfig loaded, password is undefined
password authentication failedConfig loaded, credentials are wrong
ECONNREFUSEDConfig loaded, nothing listening at that address
Knex: Timeout acquiring a connectionConfig loaded, packets are being dropped

Working out which of these you have narrows the problem enormously: the first is a build or packaging issue, the rest are runtime and network issues.

Further reading

Theodore Kelechukwu OnyejiakuDevRel and Community | Software Developer | Technical Writer

Theodore is a Technical Writer and a full-stack software developer. He loves writing technical articles, building solutions, and sharing his expertise.

Fixing TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string in Strapi
EcosystemIntermediate·5 min read

Fixing TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string in Strapi

Strapi crashes on restart after you create a component, with a path error from the component loader. The Windows bug behind it, and how to fix it.

·September 9, 2026
Finding and using Strapi design system icons in your plugin
EcosystemIntermediate·6 min read

Finding and using Strapi design system icons in your plugin

@strapi/icons ships hundreds of icons as React components with no visual index. How to browse them, use them in a plugin, and generate a reference.

·September 9, 2026
Uploading large files to Strapi: every limit you have to raise
EcosystemIntermediate·6 min read

Uploading large files to Strapi: every limit you have to raise

"The uploaded file exceeds the maximum allowed asset size" comes from one of four independent limits. Each one, and the order to change them in.

·September 9, 2026