symfony/http-foundation · error · InvalidArgumentException

URLs without scheme are not supported to configure the…

Error message

URLs without scheme are not supported to configure the PdoSessionHandler.

What it means

When the handler receives a URL instead of a raw PDO DSN, buildDsnFromUrl() parses it with parse_url(). If the URL has no scheme (e.g. 'localhost/db' or a bare DSN passed where a URL was expected), the code cannot map it to a PDO driver and throws an InvalidArgumentException.

Solutions

  1. Ensure the URL includes a scheme, e.g. pdo-mysql://user:pass@host/dbname or mysql://...
  2. If you meant to pass a raw PDO DSN (e.g. 'mysql:host=localhost;dbname=app'), that is supported too — just don't mix formats; verify the env var value
  3. Check the framework session handler config (handler_id / dsn option) so a proper URL is injected

Example fix

// before
$handler = new \PdoSessionHandler('localhost/sessions');
// after
$handler = new \PdoSessionHandler('mysql://user:pass@localhost/sessions');
Defensive patterns

Strategy: validation

Validate before calling

$url = $_ENV['DATABASE_URL'] ?? '';
if ($url !== '' && strpbrk(parse_url($url, PHP_URL_SCHEME) ?: '', 'a') === false || parse_url($url, PHP_URL_SCHEME) === false || parse_url($url, PHP_URL_SCHEME) === null) {
    throw new \InvalidArgumentException('DATABASE_URL must include a scheme, e.g. mysql://user:pass@host/db');
}

Type guard

function hasScheme(string $url): bool {
    return is_string(parse_url($url, PHP_URL_SCHEME)) && parse_url($url, PHP_URL_SCHEME) !== '';
}

Try / catch

try {
    $handler = new \PdoSessionHandler($dsnOrUrl, $options);
} catch (\InvalidArgumentException $e) {
    // log config error: URL/DSN malformed or missing scheme
}

Prevention

When it happens

Trigger: Passing a connection string/URL without a scheme (e.g. 'database_host/dbname' or missing 'pdo-' prefix style) as the first constructor argument of PdoSessionHandler, so parse_url() yields no 'scheme' key.

Common situations: Config mistakes where an env var like DATABASE_URL is empty or truncated; confusing a PDO DSN with the URL form; YAML/env interpolation dropping the scheme part.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of symfony/http-foundation@5aea19cd67 (2026-09-13). Data as JSON: /api/errors/afddae1a57b205f9. Report an issue: GitHub.

Appendix: source

Thrown at Session/Storage/Handler/PdoSessionHandler.php:529

        $params = parse_url($url);

        if (false === $params) {
            return $dsnOrUrl; // If the URL is not valid, let's assume it might be a DSN already.
        }

        $params = array_map('rawurldecode', $params);

        // Override the default username and password. Values passed through options will still win over these in the constructor.
        if (isset($params['user'])) {
            $this->username = $params['user'];
        }

        if (isset($params['pass'])) {
            $this->password = $params['pass'];
        }

        if (!isset($params['scheme'])) {
            throw new \InvalidArgumentException('URLs without scheme are not supported to configure the PdoSessionHandler.');
        }

        $driverAliasMap = [
            'mssql' => 'sqlsrv',
            'mysql2' => 'mysql', // Amazon RDS, for some weird reason
            'postgres' => 'pgsql',
            'postgresql' => 'pgsql',
            'sqlite3' => 'sqlite',
        ];

        $driver = $driverAliasMap[$params['scheme']] ?? $params['scheme'];

        // Doctrine DBAL supports passing its internal pdo_* driver names directly too (allowing both dashes and underscores). This allows supporting the same here.
        if (str_starts_with($driver, 'pdo_') || str_starts_with($driver, 'pdo-')) {
            $driver = substr($driver, 4);
        }

        $dsn = null;

View on GitHub (pinned to 5aea19cd67)