symfony/translation · error · InvalidArgumentException

The translation provider DSN is invalid.

Error message

The translation provider DSN is invalid.

What it means

Translation provider Dsn::__construct parses the DSN string with parse_url. If parse_url fails (the string is not a well-formed URL), an InvalidArgumentException is thrown because the rest of Dsn cannot be built. This is the first validity gate for every translation provider DSN.

Solutions

  1. Fix the DSN syntax so it is a valid URL: scheme://user:pass@host:port/path.
  2. rawurlencode the user and password (especially secrets with @ : / % ? # characters).
  3. Print the DSN source (env var, config) and check for trimming/interpolation issues — never log the secret itself.
  4. Test with `var_dump(parse_url($dsn))` to see exactly what parse_url rejects.

Example fix

// before
new Dsn('loco://' . $key); // $key = 'a b@c%' -> parse_url fails

// after
new Dsn('loco://' . rawurlencode($key) . '@api.locoapp');
Defensive patterns

Strategy: try-catch

Validate before calling

if (false === parse_url($dsn)) {
    throw new \InvalidArgumentException('Malformed translation provider DSN');
}

Try / catch

try {
    $dsn = new Dsn($rawDsn);
} catch (\InvalidArgumentException $e) {
    // log a redacted version of $rawDsn and fix quoting/encoding
}

Prevention

When it happens

Trigger: Passing a malformed DSN such as 'loco://' + unencoded special characters (spaces, bare '%', broken brackets) or a completely non-URL string like 'my translation key' to new Dsn(...) or a provider factory.

Common situations: Secrets containing special characters like @, :, /, or % not rawurlencoded; missing scheme separator typos ('loco://host:' with trailing garbage); shell interpolation producing empty/garbled DSNs in env vars.

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/translation@ae9e8a51bc (2026-09-15). Data as JSON: /api/errors/519c1c7b14c6b628. Report an issue: GitHub.

Appendix: source

Thrown at Provider/Dsn.php:37

 * @author Oskar Stark <oskarstark@googlemail.com>
 */
final class Dsn
{
    private ?string $scheme;
    private ?string $host;
    private ?string $user;
    private ?string $password;
    private ?int $port;
    private ?string $path;
    private array $options = [];
    private string $originalDsn;

    public function __construct(#[\SensitiveParameter] string $dsn)
    {
        $this->originalDsn = $dsn;

        if (false === $params = parse_url($dsn)) {
            throw new InvalidArgumentException('The translation provider DSN is invalid.');
        }

        if (!isset($params['scheme'])) {
            throw new InvalidArgumentException('The translation provider DSN must contain a scheme.');
        }
        $this->scheme = $params['scheme'];

        if (!isset($params['host'])) {
            throw new InvalidArgumentException('The translation provider DSN must contain a host (use "default" by default).');
        }
        $this->host = $params['host'];

        $this->user = '' !== ($params['user'] ?? '') ? rawurldecode($params['user']) : null;
        $this->password = '' !== ($params['pass'] ?? '') ? rawurldecode($params['pass']) : null;
        $this->port = $params['port'] ?? null;
        $this->path = $params['path'] ?? null;
        parse_str($params['query'] ?? '', $this->options);
    }

View on GitHub (pinned to ae9e8a51bc)