Fix “Access Denied for User” in CodeIgniter 4 on Hostinger

Trace CodeIgniter 4 MySQLi access-denied errors on Hostinger. Check the active connection group, database user, host and permissions safely.

Fix “Access Denied for User” in CodeIgniter 4 on Hostinger

When CodeIgniter reports “Access denied for user,” find the original MySQL or MariaDB error number in the restricted server or application log. The public page may show only a generic connection error. The useful question is whether the server refused the login or accepted the login but refused access to the selected database.

Keep the public site in production mode. Copy only the error number and the relevant setting names into a troubleshooting note. Leave usernames, passwords and host details out of public posts and screenshots. MySQL error reference · CodeIgniter environments

Error What to check first
1045 Check the user, password and matching host account. The server rejected authentication. The message can indicate whether a password was supplied. It does not confirm that the password was correct.
1044 Check the selected database and the user’s access to it. The server denied access to that database.
1049 Check whether the database name exists on the server you reached. This error means the named database was not found.
Connection refused, socket error or timeout Check transport, hostname and provider connection instructions first. These symptoms do not establish an authentication failure.

MySQL server error reference · MySQL connection verification

1. Match the actual hPanel database and user

Open the correct site in hPanel and go to its database management section. Record the exact database name and assigned MySQL username as displayed, including any account prefix. Make sure the user is assigned to that database and has only the access the application needs. Keep the existing production password if it is known and working elsewhere. If it needs to be rotated, identify every application or task that uses that account before making the change. Hostinger database details · Hostinger connection troubleshooting

Hostinger documents localhost for its local web-hosting database connections. Confirm which host applies to your deployment. In PHP MySQLi on Unix, localhost normally uses a Unix socket, while 127.0.0.1 uses TCP. Switching between them can change how the client connects and how account matching works. Use the provider’s documented connection settings instead of cycling through hostnames. Hostinger database details · PHP MySQLi connection transports

2. Check the connection group the failing code uses

In app/Config/Database.php, check $defaultGroup and look for an explicit group in calls such as \Config\Database::connect('reporting'). A model can also set its own $DBGroup. An environment override for database.default.password affects the default group. It will not fix a connection using reporting. Check the failing code path, and check whether it supplies an explicit connection array instead of a group. CodeIgniter database configuration · CodeIgniter database connection groups

This is an example layout for a disposable account using the default group. Substitute the exact staging values privately. Put the file at the application root outside the public directory.

database.default.hostname = localhost
database.default.database = account_ci4_staging
database.default.username = account_ci4_probe
database.default.password = "replace-with-staging-password"
database.default.DBDriver = MySQLi

Check for an outdated deployment environment variable or a cached configuration if the app appears to keep using earlier values. CodeIgniter’s dotenv loader preserves environment variables that already exist. If your app enables configuration caching, follow the cache procedure for its installed version. Avoid printing the effective configuration or its password to diagnose the issue. CodeIgniter environment variables · CodeIgniter configuration caching

3. Reproduce the error with a disposable database user

On a staging host with a MySQL command-line client, use a dedicated test user assigned to the example database. Run from the same host as the app when possible. Substitute the staging user, database and host values. The client prompts for the password without placing it in the command. Use --password without a value so the credential stays out of command history and process arguments. Keep the test output private if it includes the database account or hostname.

mysql --host=localhost \
  --user=account_ci4_probe \
  --password \
  --database=account_ci4_staging \
  --batch --skip-column-names \
  --execute='SELECT 1'

Start with the correct staging password, repeat once with a deliberately incorrect dummy password, and then repeat with the correct one. Change nothing about the live database. If you already have a second disposable database with no grants for this user, you can optionally test the same correct password against it. Keep the original permissions intact. MySQL client options

Test condition Expected result
Correct test password and database assigned to the user One result row containing 1
Wrong password for the same password-authenticated test user 1045
Correct password with an existing database the user cannot access 1044
Correct password and the original assigned database again One result row containing 1

A successful client check establishes that the test connection can run a simple read-only statement. It does not establish that PHP is reading the same configuration or that the app has permission to read its own tables.

4. Check the same connection through CodeIgniter

If you have staging SSH access and Spark, add this temporary command at app/Commands/DbProbe.php on the disposable copy. Replace 'default' if the code path you are testing uses another group. It creates a separate CodeIgniter connection instance and runs a read-only check. A passing result can come from a fallback server if the selected group has failover configured. To isolate one host, use a disposable group with an empty failover array and pConnect disabled. The probe prints a short pass or fail message without exposing connection values or creating a web endpoint. Creating Spark commands · Connection instances · Failover configuration · CodeIgniter query methods

<?php

namespace App\Commands;

use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\CLI\CLI;
use Config\Database;

final class DbProbe extends BaseCommand
{
    protected $group = 'Diagnostics';
    protected $name = 'db:probe';
    protected $description = 'Check a staging database connection.';

    public function run(array $params)
    {
        try {
            $db = Database::connect('default', false);
            $result = $db->query('SELECT 1 AS ok');
            if ($result !== false && (int) ($result->getRowArray()['ok'] ?? 0) === 1) {
                CLI::write('Staging database probe passed.');
                return EXIT_SUCCESS;
            }
        } catch (\Throwable) {
            // Suppress exception details. This catch block does not write to a restricted log.
        }

        CLI::error('Staging database probe failed.');
        return EXIT_ERROR;
    }
}

Run php spark db:probe from the staging application directory. If the client connects but Spark fails, compare the configured group, server-side environment values, selected host and PHP MySQLi availability. If Spark passes but the staged website fails, compare the CLI and web PHP configuration and check which group the specific web request uses. Then open one normal read-only page on staging that queries a known test record. That gives you a stronger application check than SELECT 1 alone. If the probe fails, use the original driver error or any available restricted staging logs to identify the cause. The probe's generic message does not identify an error code. Remove the temporary command after verifying the fix.

For a related release checklist, see DevOps for small website teams. To review who should have database or hosting access, start with our small-business cybersecurity plan.

Test scope · The walkthroughs use a disposable application, example hostnames and a disposable database account. The HTTP status codes and MySQL responses in the tables are expected results for the stated setup. They were not observed on a Hostinger server.

Share

What's Your Reaction?

Like Like 0
Dislike Dislike 0
Love Love 0
Funny Funny 0
Angry Angry 0
Sad Sad 0
Wow Wow 0