{"record":{"id":"6615f9ccb37853af","repo":"flarum/framework","slug":"both-text-and-html-views-must-be-provided-to-send-an-email","errorCode":null,"errorMessage":"Both text and html views must be provided to send an email notification of type'.$blueprint::getType().'.","messagePattern":"Both text and html views must be provided to send an email notification of type'\\.\\$blueprint::getType\\(\\)\\.'\\.","errorType":"exception","errorClass":"InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"framework/core/src/Notification/NotificationMailer.php","lineNumber":88,"sourceCode":"    }\n\n    /**\n     * Retrieves the email views from the blueprint, and enforces that both a\n     * plain text and HTML view are provided.\n     *\n     * @param MailableInterface&BlueprintInterface $blueprint\n     * @return array{\n     *     text: string,\n     *     html: string\n     * }\n     */\n    protected function getEmailViews(MailableInterface&BlueprintInterface $blueprint): array\n    {\n        $views = $blueprint->getEmailViews();\n\n        // check that both text and html views are provided\n        if (! Arr::has($views, ['text', 'html'])) {\n            throw new \\InvalidArgumentException('Both text and html views must be provided to send an email notification of type'.$blueprint::getType().'.');\n        }\n\n        return $views;\n    }\n}\n","sourceCodeStart":70,"sourceCodeEnd":94,"githubUrl":"https://github.com/flarum/framework/blob/4b939f685389bfe8a380e9e28ddf305a1c66950c/framework/core/src/Notification/NotificationMailer.php#L70-L94","documentation":"Flarum's NotificationMailer sends email notifications via Mailables. getEmailViews() requires the notification blueprint's getEmailViews() to return an array containing BOTH 'text' and 'html' keys; if either is missing it throws this InvalidArgumentException, since emails must ship a plain-text and an HTML variant.","triggerScenarios":"A notification Blueprint class returns an array from getEmailViews() that lacks the 'html' or 'text' key (e.g. only ['html' => 'emails.notification'] or an empty array), and the notification is then sent via NotificationMailer::send().","commonSituations":"A custom extension notification blueprint forgot the text view; a view name typo/misplaced blade template removed a key; upgrading Flarum made the dual-view requirement stricter than an older blueprint implementation.","solutions":["Return both keys from getEmailViews(): ['text' => ..., 'html' => ...].","Create the missing text (or html) view template and reference it.","Double-check the blueprint's getType() naming shown in the message to find the offending class.","For upgrades, align custom blueprints with the current Flarum Mailable blueprint interface requirements."],"exampleFix":"// before\npublic function getEmailViews(): array\n{\n    return ['html' => 'emails.new-post'];\n}\n// after\npublic function getEmailViews(): array\n{\n    return ['html' => 'emails.new-post', 'text' => 'emails.new-post-text'];\n}","handlingStrategy":"validation","validationCode":"$views = $blueprint->getEmailViews();\nif (!Arr::has($views, ['text', 'html'])) {\n    throw new \\LogicException(static::class.' must provide both text and html email views');\n}","typeGuard":"function hasBothEmailViews(array $views): bool {\n    return isset($views['text']) && isset($views['html']);\n}","tryCatchPattern":"try {\n    $mailer->send($notification, $users);\n} catch (\\InvalidArgumentException $e) {\n    if (str_contains($e->getMessage(), 'Both text and html views')) {\n        Log::error('Notification blueprint missing email views', ['type' => $notification::getType()]);\n    } else {\n        throw $e;\n    }\n}","preventionTips":["Always return both 'text' and 'html' keys in getEmailViews().","Unit-test every custom notification blueprint's getEmailViews() output.","Add a CI check asserting blueprint view templates exist."],"tags":["php","email","notification","validation","flarum"],"backgroundTag":"missing-required-argument","analyzedSha":"4b939f685389bfe8a380e9e28ddf305a1c66950c","analyzedAt":"2026-09-15T18:09:20.879Z","contentChangedAt":"2026-09-15T18:09:20.879Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}