{"record":{"id":"9449d3daa6037aa9","repo":"Billionmail/BillionMail","slug":"hex-decode-failed-w","errorCode":null,"errorMessage":"hex decode failed: %w","messagePattern":"hex decode failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/service/mail_service/sending.go","lineNumber":164,"sourceCode":"\t\terr = errors.New(\"Email Sender not configured\")\n\t\treturn\n\t}\n\n\treturn\n}\n\n// PasswordPlainByEmail\nfunc PasswordPlainByEmail(ctx context.Context, email string) (string, error) {\n\tval, err := g.DB().Model(\"mailbox\").Where(\"username\", email).Value(\"password_encode\")\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"query password failed: %w\", err)\n\t}\n\tif val.IsEmpty() {\n\t\treturn \"\", fmt.Errorf(\"password not found for %s\", email)\n\t}\n\trawHex, err := hex.DecodeString(val.String())\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"hex decode failed: %w\", err)\n\t}\n\tplainBytes, err := base64.StdEncoding.DecodeString(string(rawHex))\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"base64 decode failed: %w\", err)\n\t}\n\treturn string(plainBytes), nil\n}\n\n// Close closes the SMTP connection\nfunc (e *EmailSender) Close() {\n\t_ = e.Disconnect()\n}\n\n// Connect establishes an SMTP connection\nfunc (e *EmailSender) Connect() error {\n\te.mutex.Lock()\n\tdefer e.mutex.Unlock()\n","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/mail_service/sending.go#L146-L182","documentation":"The password_encode column is expected to hold a hex-encoded string. hex.DecodeString fails if the stored value contains non-hex characters or has odd length, producing 'hex decode failed' with the cause wrapped via %w.","triggerScenarios":"PasswordPlainByEmail reads a password_encode value that was stored in a different format (plain text, raw base64, bcrypt hash) or was corrupted/truncated, so it is not valid hex.","commonSituations":"Admin pasted a plain password or base64 string directly into the column; another tool/binary wrote the column in its own format; partial row update truncated the value to odd length.","solutions":["Inspect the stored value: it must be valid hex (even length, [0-9a-f] only).","Re-encode the password as base64 then hex before storing, or use the app's own password-set flow.","Reset the mailbox password via the admin UI so it is stored in the expected format.","Check for a schema/version mismatch — older versions may have stored passwords differently."],"exampleFix":"// before\nUPDATE mailbox SET password_encode='mypassword' WHERE username='x';\n// after\n-- store: base64(password) encoded as hex\nb64 := base64.StdEncoding.EncodeToString([]byte(\"mypassword\"))\nenc := hex.EncodeToString([]byte(b64))\n-- UPDATE mailbox SET password_encode='<enc>' WHERE username='x';","handlingStrategy":"validation","validationCode":"v, err := g.DB().Model(\"mailbox\").Where(\"username\", email).Value(\"password_encode\")\nif err == nil && !v.IsEmpty() {\n    if _, derr := hex.DecodeString(v.String()); derr != nil {\n        return fmt.Errorf(\"password_encode for %s is not valid hex; reset the password\", email)\n    }\n}","typeGuard":"func isHex(s string) bool {\n    _, err := hex.DecodeString(s)\n    return len(s)%2 == 0 && err == nil\n}","tryCatchPattern":"pass, err := PasswordPlainByEmail(ctx, email)\nif err != nil {\n    var hexErr *hex.InvalidByteError\n    if errors.As(err, &hexErr) {\n        return fmt.Errorf(\"mailbox %s password stored in wrong format; reset via admin UI\", email)\n    }\n    return err\n}","preventionTips":["Set passwords only through the app's own password-set flow.","Validate stored format (hex of base64) after any data import.","Document the storage scheme for anyone seeding rows manually."],"tags":["encoding","hex","password","data-format"],"backgroundTag":"invalid-hex-encoding","analyzedSha":"fc36c76c050c3775c5e899faf7403cf0262d2744","analyzedAt":"2026-09-05T21:28:54.019Z","contentChangedAt":"2026-09-05T21:28:54.019Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}