monicahq/monica · error · Exception
Only email can be sent.
Error message
Only email can be sent.
What it means
SendTestEmail sends a test message on a user notification channel. It loads the channel belonging to the author via findOrFail (unknown id -> 404) and then requires type === UserNotificationChannel::TYPE_EMAIL ('email'); any other type throws a bare \Exception which Laravel renders as a 500.
Source
Thrown at app/Domains/Settings/ManageNotificationChannels/Services/SendTestEmail.php:63
public function execute(array $data): UserNotificationChannel
{
$this->data = $data;
$this->validate();
$this->send();
$this->log();
return $this->userNotificationChannel;
}
private function validate(): void
{
$this->validateRules($this->data);
$this->userNotificationChannel = $this->author->notificationChannels()
->findOrFail($this->data['user_notification_channel_id']);
if ($this->userNotificationChannel->type !== UserNotificationChannel::TYPE_EMAIL) {
throw new Exception('Only email can be sent.');
}
}
private function send(): void
{
Mail::to($this->userNotificationChannel->content)->send(
new TestEmailSent($this->userNotificationChannel)
);
}
private function log(): void
{
UserNotificationSent::create([
'user_notification_channel_id' => $this->userNotificationChannel->id,
'sent_at' => Carbon::now(),
'subject_line' => trans('Test email for Monica'),
]);
}View on GitHub (pinned to e08e917341)
Solutions
- Pass the id of a channel whose type is 'email'
- Reload the notification channels list before triggering the test send
- Only offer 'send test email' for email channels in the UI
- Catch the exception in the controller and return 422 with the message instead of a 500
Example fix
// before
app(SendTestEmail::class)->execute([
'user_notification_channel_id' => $channelId, // might be a telegram channel
]);
// after
$channel = $author->notificationChannels()->findOrFail($channelId);
abort_unless($channel->type === UserNotificationChannel::TYPE_EMAIL, 422, 'Only email can be sent.');
app(SendTestEmail::class)->execute([
'user_notification_channel_id' => $channel->id,
]); Defensive patterns
Strategy: validation
Validate before calling
// Validate before calling: the channel must exist and be an email channel
$channel = $author->notificationChannels()->find($data['user_notification_channel_id']);
if ($channel === null) {
throw ValidationException::withMessages(['user_notification_channel_id' => 'Channel not found.']);
}
if ($channel->type !== UserNotificationChannel::TYPE_EMAIL) {
throw ValidationException::withMessages(['user_notification_channel_id' => 'Only email channels can receive a test email.']);
} Type guard
function isEmailChannel(?UserNotificationChannel $channel): bool
{
return $channel !== null
&& $channel->type === UserNotificationChannel::TYPE_EMAIL;
} Try / catch
try {
app(SendTestEmail::class)->execute($data);
} catch (\Exception $e) {
if ($e->getMessage() === 'Only email can be sent.') {
// wrong channel type: surface as 422 and refresh the channel list
throw ValidationException::withMessages(['user_notification_channel_id' => $e->getMessage()]);
}
throw $e;
} Prevention
- Refresh the channel list before showing per-channel test actions
- Bind test actions to the channel type at render time (email button only on email rows)
- Scope channel selection queries to type where the operation is type-specific
- Map this \Exception to 422 at the boundary so clients never see a 500
When it happens
Trigger: Invoking the 'send test email' action with the user_notification_channel_id of a channel whose type is 'telegram' (the only other type in this codebase) — typically a stale frontend still holding an id from before the channel was created or switched.
Common situations: UI channel list not refreshed after editing channels, mixed-up ids between the email and telegram channel forms, or API consumers hard-coding the wrong channel id.
Related errors
- Only telegram messages can be sent.
- Could not get address book data.
- No address book found
- $e->getMessage()
- The user does not belong to the vault's account.
AI-assisted analysis of monicahq/monica@e08e917341 (2026-08-17).
Data as JSON: /api/errors/c3142e3f4bb18850.
Report an issue: GitHub.