SigNoz/signoz · error

CodeInvalidInput

CodeInvalidInput

Error message

missing secret for CRAM-MD5 auth mechanism

What it means

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.

Source

Thrown at pkg/smtp/client/smtp.go:279

	if err = closeOnce(); err != nil {
		return errors.WrapInternalf(err, errors.CodeInternal, "failed to deliver")
	}

	success = true
	return nil
}

// auth resolves a string of authentication mechanisms.
func (c *Client) smtpAuth(_ context.Context, mechs string) (smtp.Auth, error) {
	username := c.auth.Username

	var errs []error
	for _, mech := range strings.Split(mechs, " ") {
		switch mech {
		case "CRAM-MD5":
			secret := c.auth.Secret
			if secret == "" {
				errs = append(errs, errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, "missing secret for CRAM-MD5 auth mechanism"))
				continue
			}
			return smtp.CRAMMD5Auth(username, secret), nil

		case "PLAIN":
			password := c.auth.Password
			if password == "" {
				errs = append(errs, errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, "missing password for PLAIN auth mechanism"))
				continue
			}
			identity := c.auth.Identity

			return smtp.PlainAuth(identity, username, password, c.host), nil
		case "LOGIN":
			password := c.auth.Password
			if password == "" {
				errs = append(errs, errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, "missing password for LOGIN auth mechanism"))
				continue

View on GitHub (pinned to 5069bf80b0)

Solutions

  1. Set the auth Secret (CRAM-MD5 uses the secret in place of a password) in the SMTP client config
  2. If you only have a password, restrict/prefer PLAIN or LOGIN so CRAM-MD5 is not chosen
  3. Check errors.Join output: multiple mechanism errors may be combined; fix all reported ones

Example fix

// before
auth := smtpclient.Auth{Username: u} // Secret empty

// after
auth := smtpclient.Auth{Username: u, Secret: secret}
Defensive patterns

Strategy: validation

Validate before calling

func validateSMTPAuth(a smtpclient.Auth) error {
    if a.Username == "" {
        return fmt.Errorf("smtp username required")
    }
    if a.Secret == "" {
        return fmt.Errorf("smtp secret required for CRAM-MD5")
    }
    return nil
}

Try / catch

auth, err := client.smtpAuth(ehloMechs)
if err != nil {
    return fmt.Errorf("smtp auth config: %w", err) // errs are joined; report all
}

Prevention

When it happens

Trigger: Configuring the SMTP client with a username but no secret (Secret field empty) while the server offers CRAM-MD5, and no other mechanism succeeds.

Common situations: 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.

Related errors


AI-assisted analysis of SigNoz/signoz@5069bf80b0 (2026-08-28). Data as JSON: /api/errors/ee2e5a1e6054f2ed. Report an issue: GitHub.