cakephp/cakephp · error · BadMethodCallException

Transport was not defined. You must set on using…

Error message

Transport was not defined. You must set on using setTransport() or set `transport` option in your mailer profile.

What it means

Mailer::getTransport() returns the configured AbstractTransport and throws BadMethodCallException if no transport was ever set. Sending requires a transport (Smtp, Mail, Debug, etc.) either set explicitly or via the mailer profile.

Solutions

  1. Call $mailer->setTransport('default') (or a transport instance) before deliver().
  2. Add 'transport' => 'default' to the email profile passed to setProfile().
  3. Ensure the transport name referenced is itself configured via EmailTransport config.
  4. In tests, set a Debug transport: $mailer->setTransport(new DebugTransport()).

Example fix

// before
(new MyMailer())->deliver('hi');
// after
(new MyMailer())->setTransport('default')->deliver('hi');
Defensive patterns

Strategy: validation

Validate before calling

$reflection = new \ReflectionProperty($mailer, 'transport');
$reflection->setAccessible(true);
if ($reflection->getValue($mailer) === null) {
    $mailer->setTransport('default');
}

Try / catch

try {
    $mailer->deliver('message');
} catch (\BadMethodCallException $e) {
    \Cake\Log\Log::error('Mailer has no transport: ' . $e->getMessage());
}

Prevention

When it happens

Trigger: Calling deliver()/getTransport() on a Mailer whose transport is still null: neither setTransport() was called nor did the profile include a 'transport' key.

Common situations: Instantiating a Mailer directly without a profile; a profile array that omits 'transport'; tests constructing Mailer manually; profile loaded but transport name itself unconfigured.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of cakephp/cakephp@1128eba9b0 (2026-09-12). Data as JSON: /api/errors/0c1cbed4593f8394. Report an issue: GitHub.

Appendix: source

Thrown at src/Mailer/Mailer.php:482

    {
        if (is_string($name)) {
            $this->transport = TransportFactory::get($name);
        } else {
            $this->transport = $name;
        }

        return $this;
    }

    /**
     * Gets the transport.
     *
     * @return \Cake\Mailer\AbstractTransport
     */
    public function getTransport(): AbstractTransport
    {
        if ($this->transport === null) {
            throw new BadMethodCallException(
                'Transport was not defined. '
                . 'You must set on using setTransport() or set `transport` option in your mailer profile.',
            );
        }

        return $this->transport;
    }

    /**
     * Backup message, renderer, transport instances before an action is run.
     *
     * @return void
     */
    protected function backup(): void
    {
        $this->clonedInstances['message'] = clone $this->message;
        if ($this->renderer !== null) {
            $this->clonedInstances['renderer'] = clone $this->renderer;

View on GitHub (pinned to 1128eba9b0)