{"record":{"id":"2c8c062506606a65","repo":"immich-app/immich","slug":"invalid-smtp-configuration","errorCode":null,"errorMessage":"Invalid SMTP configuration","messagePattern":"Invalid SMTP configuration","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/src/services/notification.service.ts","lineNumber":137,"sourceCode":"    this.websocketRepository.clientBroadcast('AppRestartV1', {\n      isMaintenanceMode: state.isMaintenanceMode,\n    });\n\n    this.websocketRepository.serverSend('AppRestart', state);\n  }\n\n  @OnEvent({ name: 'ConfigValidate', priority: -100 })\n  async onConfigValidate({ oldConfig, newConfig }: ArgOf<'ConfigValidate'>) {\n    try {\n      if (\n        newConfig.notifications.smtp.enabled &&\n        !isEqualObject(oldConfig.notifications.smtp, newConfig.notifications.smtp)\n      ) {\n        await this.emailRepository.verifySmtp(newConfig.notifications.smtp.transport);\n      }\n    } catch (error: Error | any) {\n      this.logger.error(`Failed to validate SMTP configuration: ${error}`, error?.stack);\n      throw new Error('Invalid SMTP configuration', { cause: error });\n    }\n  }\n\n  @OnEvent({ name: 'AssetHide' })\n  onAssetHide({ assetId, userId }: ArgOf<'AssetHide'>) {\n    this.websocketRepository.clientSend('on_asset_hidden', userId, assetId);\n  }\n\n  @OnEvent({ name: 'AssetShow' })\n  async onAssetShow({ assetId }: ArgOf<'AssetShow'>) {\n    await this.jobRepository.queue({ name: JobName.AssetGenerateThumbnails, data: { id: assetId, notify: true } });\n  }\n\n  @OnEvent({ name: 'AssetTrash' })\n  onAssetTrash({ assetId, userId }: ArgOf<'AssetTrash'>) {\n    this.websocketRepository.clientSend('on_asset_trash', userId, [assetId]);\n  }\n","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/server/src/services/notification.service.ts#L119-L155","documentation":"Thrown by NotificationService.onConfigValidate when the server config change event detects a modified notifications.smtp section and the new SMTP transport fails verifySmtp. The config validation event therefore fails with 'Invalid SMTP configuration', with the underlying SMTP error attached as cause, preventing the config change from being accepted.","triggerScenarios":"Saving system settings (PUT /system-config) where newConfig.notifications.smtp differs from the old config and the new transport cannot connect/authenticate (bad host, port, credentials, TLS mode).","commonSituations":"Admin edits SMTP settings in the Immich admin UI and mistypes the host or password; switching between TLS/STARTTLS ports; migrating to a new mail provider without updating credentials; firewall changes after an infra move.","solutions":["Inspect the cause/log line 'Failed to validate SMTP configuration' for the underlying SMTP error and fix that (host, port, credentials, TLS)","Re-enter credentials carefully; use an app password where required","Match security mode to port (465 implicit TLS, 587 STARTTLS)","Confirm outbound SMTP connectivity from the server host/container, then resubmit the config"],"exampleFix":"// before\nnotifications.smtp.transport = { host: 'mail.example.com', port: 465, secure: false } // plaintext on implicit-TLS port\n// after\nnotifications.smtp.transport = { host: 'mail.example.com', port: 465, secure: true }","handlingStrategy":"validation","validationCode":"// Before saving system config, verify the new SMTP transport yourself\nimport nodemailer from 'nodemailer';\nconst t = nodemailer.createTransport(newTransport);\nawait t.verify(); // throws with the same underlying error verifySmtp would\nawait api.systemConfigApi.updateConfig({ notifications: { smtp: { ...smtp, transport: newTransport } } });","typeGuard":"function smtpTransportChanged(oldCfg, newCfg) {\n  return !!newCfg?.notifications?.smtp?.transport &&\n    JSON.stringify(oldCfg?.notifications?.smtp?.transport) !== JSON.stringify(newCfg.notifications.smtp.transport);\n}","tryCatchPattern":"try {\n  await api.systemConfigApi.updateConfig(newConfig);\n} catch (e) {\n  if (String(e.message).includes('Invalid SMTP configuration')) {\n    console.error('Config rejected; SMTP cause:', e.cause ?? e.response?.data); // correct transport then resubmit\n  } else throw e;\n}","preventionTips":["Run an SMTP verify (e.g. nodemailer transport.verify()) before saving config changes","Keep the previous working transport handy to roll back if validation fails","Test connectivity from the server host, not your workstation","Document port/security-mode pairings to avoid TLS/STARTTLS mismatches"],"tags":["smtp","config-validation","email","system-config"],"backgroundTag":"invalid-config-value","analyzedSha":"e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c","analyzedAt":"2026-09-15T07:20:19.675Z","contentChangedAt":"2026-09-15T07:20:19.675Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}