usememos/memos · error

notification email cannot enable both useTls and useSsl

Error message

notification email cannot enable both useTls and useSsl

What it means

Thrown when an enabled notification email config sets both useTls and useSsl to true. These select mutually exclusive transport security modes: useTls means STARTTLS on the plain port, useSsl means implicit TLS (SMTPS, typically port 465). Enabling both is ambiguous, so the deployment validator rejects the file at startup instead of guessing.

Source

Thrown at store/deployment_config.go:280

					return errors.Errorf("storageSetting default S3 config.%s is required", field.name)
				}
			}
		}
	case storepb.InstanceSettingKey_MEMO_RELATED:
		if setting.GetMemoRelatedSetting() == nil {
			return errors.New("memoRelatedSetting must be populated for key MEMO_RELATED")
		}
	case storepb.InstanceSettingKey_NOTIFICATION:
		notification := setting.GetNotificationSetting()
		if notification == nil {
			return errors.New("notificationSetting must be populated for key NOTIFICATION")
		}
		if email := notification.Email; email != nil && email.Enabled {
			if strings.TrimSpace(email.SmtpHost) == "" || email.SmtpPort <= 0 || strings.TrimSpace(email.FromEmail) == "" {
				return errors.New("enabled notification email requires smtpHost, a positive smtpPort, and fromEmail")
			}
			if email.UseTls && email.UseSsl {
				return errors.New("notification email cannot enable both useTls and useSsl")
			}
		}
	case storepb.InstanceSettingKey_AI:
		if setting.GetAiSetting() == nil {
			return errors.New("aiSetting must be populated for key AI")
		}
		if err := normalizeDeploymentAISetting(setting.GetAiSetting()); err != nil {
			return err
		}
	case storepb.InstanceSettingKey_BASIC, storepb.InstanceSettingKey_TAGS:
		return errors.Errorf("key %s cannot be deployment configured", setting.Key)
	default:
		return errors.Errorf("unsupported instance setting key %s", setting.Key)
	}
	return nil
}

func normalizeDeploymentAISetting(setting *storepb.InstanceAISetting) error {

View on GitHub (pinned to 14d757ce1f)

Solutions

  1. Pick one mode: port 587/25 with "useTls": true, "useSsl": false; or port 465 with "useSsl": true, "useTls": false.
  2. Match the mode to the port your SMTP provider documents.

Example fix

// before
{ "enabled": true, "smtpPort": 465, "useTls": true, "useSsl": true, ... }

// after
{ "enabled": true, "smtpPort": 465, "useTls": false, "useSsl": true, ... }
Defensive patterns

Strategy: validation

Validate before calling

if e.UseTls && e.UseSsl {
    return errors.New("email cannot set both useTls and useSsl")
}

Type guard

func tlsModeIsUnambiguous(e *storepb.EmailSetting) bool { return !(e.GetUseTls() && e.GetUseSsl()) }

Prevention

When it happens

Trigger: "email": { "enabled": true, "useTls": true, "useSsl": true, ... } — often from copy-pasting two example configs or setting every boolean in the block to true.

Common situations: Operators flipping all security flags on assuming 'more TLS is safer'; port confusion (587 wants useTls, 465 wants useSsl).

Related errors


AI-assisted analysis of usememos/memos@14d757ce1f (2026-08-15). Data as JSON: /api/errors/52ff95412f22ec2d. Report an issue: GitHub.