{"record":{"id":"ee2e5a1e6054f2ed","repo":"SigNoz/signoz","slug":"codeinvalidinput-ee2e5a","errorCode":"CodeInvalidInput","errorMessage":"missing secret for CRAM-MD5 auth mechanism","messagePattern":"missing secret for CRAM-MD5 auth mechanism","errorType":"error_code","errorClass":null,"httpStatus":400,"severity":"error","filePath":"pkg/smtp/client/smtp.go","lineNumber":279,"sourceCode":"\tif err = closeOnce(); err != nil {\n\t\treturn errors.WrapInternalf(err, errors.CodeInternal, \"failed to deliver\")\n\t}\n\n\tsuccess = true\n\treturn nil\n}\n\n// auth resolves a string of authentication mechanisms.\nfunc (c *Client) smtpAuth(_ context.Context, mechs string) (smtp.Auth, error) {\n\tusername := c.auth.Username\n\n\tvar errs []error\n\tfor _, mech := range strings.Split(mechs, \" \") {\n\t\tswitch mech {\n\t\tcase \"CRAM-MD5\":\n\t\t\tsecret := c.auth.Secret\n\t\t\tif secret == \"\" {\n\t\t\t\terrs = append(errs, errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, \"missing secret for CRAM-MD5 auth mechanism\"))\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn smtp.CRAMMD5Auth(username, secret), nil\n\n\t\tcase \"PLAIN\":\n\t\t\tpassword := c.auth.Password\n\t\t\tif password == \"\" {\n\t\t\t\terrs = append(errs, errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, \"missing password for PLAIN auth mechanism\"))\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tidentity := c.auth.Identity\n\n\t\t\treturn smtp.PlainAuth(identity, username, password, c.host), nil\n\t\tcase \"LOGIN\":\n\t\t\tpassword := c.auth.Password\n\t\t\tif password == \"\" {\n\t\t\t\terrs = append(errs, errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, \"missing password for LOGIN auth mechanism\"))\n\t\t\t\tcontinue","sourceCodeStart":261,"sourceCodeEnd":297,"githubUrl":"https://github.com/SigNoz/signoz/blob/5069bf80b08f1f00d7e014eccc09902f9871004f/pkg/smtp/client/smtp.go#L261-L297","documentation":"When the SMTP server advertises CRAM-MD5 and the client picks it, smtpAuth requires auth.Secret to be non-empty to build the CRAM-MD5 credential. An empty Secret accumulates this error, which is returned joined with other mechanism errors after the loop.","triggerScenarios":"Configuring the SMTP client with a username but no secret (Secret field empty) while the server offers CRAM-MD5, and no other mechanism succeeds.","commonSituations":"Config files that set password but not secret, env vars for the secret not set, or a provider switching to advertise CRAM-MD5 first so PLAIN is never reached once CRAM-MD5 errors continue the loop.","solutions":["Set the auth Secret (CRAM-MD5 uses the secret in place of a password) in the SMTP client config","If you only have a password, restrict/prefer PLAIN or LOGIN so CRAM-MD5 is not chosen","Check errors.Join output: multiple mechanism errors may be combined; fix all reported ones"],"exampleFix":"// before\nauth := smtpclient.Auth{Username: u} // Secret empty\n\n// after\nauth := smtpclient.Auth{Username: u, Secret: secret}","handlingStrategy":"validation","validationCode":"func validateSMTPAuth(a smtpclient.Auth) error {\n    if a.Username == \"\" {\n        return fmt.Errorf(\"smtp username required\")\n    }\n    if a.Secret == \"\" {\n        return fmt.Errorf(\"smtp secret required for CRAM-MD5\")\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"auth, err := client.smtpAuth(ehloMechs)\nif err != nil {\n    return fmt.Errorf(\"smtp auth config: %w\", err) // errs are joined; report all\n}","preventionTips":["Validate SMTP credentials at startup, not on first send","Log which mechanism the client selected"],"tags":["go","smtp","cram-md5","auth-config"],"backgroundTag":"smtp-auth-failed","analyzedSha":"5069bf80b08f1f00d7e014eccc09902f9871004f","analyzedAt":"2026-08-28T06:22:12.824Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}