AlexxIT/go2rtc · error
multitrans: auth failed
Error message
multitrans: auth failed: ${res.Status} What it means
In the second leg of the multitrans digest handshake, after the client sends the Authorization header, the server must reply 200 OK with a Session header. Any other status means authentication was rejected or the challenge failed, so the handshake aborts with the server's status line embedded in the message.
Solutions
- Verify the credentials (username/password) configured on the multitrans client match the device account.
- Check the device supports the digest algorithm the client uses; update firmware or client if it requires SHA-256.
- Re-attempt Dial in case of a stale nonce (nonce counts/nc issues); avoid sharing one device session between processes.
- Check device logs for auth rejection reasons (locked account, IP filtering).
Example fix
// before
client := multitrans.New(host, "admin", "wrongpass")
// after
client := multitrans.New(host, "admin", os.Getenv("CAMERA_PASSWORD")) Defensive patterns
Strategy: retry
Validate before calling
// verify credentials with a plain digest probe before Dial
req, _ := http.NewRequest("GET", deviceURL, nil)
resp, err := httpClient.Do(req) // then perform digest round-trip manually
if err != nil || resp.StatusCode == http.StatusUnauthorized {
return errors.New("credentials rejected by device")
} Try / catch
var lastErr error
for i := 0; i < 3; i++ {
if err := client.Dial(ctx); err == nil { break }
else if strings.Contains(err.Error(), "auth failed") {
lastErr = err
time.Sleep(500 * time.Millisecond) // retry in case of stale nonce
continue
}
return err
} Prevention
- Store device passwords in a secret manager, not hardcoded config.
- Test credentials against the device web UI when integrating.
- Avoid sharing one camera account across many concurrent clients.
- Check firmware digest algorithm support (MD5 vs SHA-256) up front.
When it happens
Trigger: Calling Dial; the digest Authorization response sent in handshake gets a non-200 status (typically 401 again after the computed digest response is wrong).
Common situations: Wrong username/password in client config; realm/nonce mismatch caused by clock skew or retries; device account locked; firmware expecting a different digest algorithm (MD5 vs SHA-256).
Related errors
- multitrans: expected 401, got
- milesone: authentication failed:
- wrong response:
- wrong auth response
- multitrans: no session
AI-assisted analysis of AlexxIT/go2rtc@c245815e75 (2026-09-07).
Data as JSON: /api/errors/5dae9cb6062e7a54.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/multitrans/client.go:152
response := tcp.HexMD5(ha1, nonce, ha2)
authHeader := fmt.Sprintf(`Digest username="%s", realm="%s", nonce="%s", uri="%s", response="%s"`,
user, realm, nonce, uri, response)
data = fmt.Sprintf("MULTITRANS %s RTSP/1.0\r\nCSeq: 1\r\nAuthorization: %s\r\nX-Client-UUID: %s\r\n\r\n",
uri, authHeader, uid)
if _, err = c.conn.Write([]byte(data)); err != nil {
return err
}
res, err = tcp.ReadResponse(c.rd)
if err != nil {
return err
}
if res.StatusCode != http.StatusOK {
return errors.New("multitrans: auth failed: " + res.Status)
}
// Session: 7116520596809429228
session := res.Header.Get("Session")
if session == "" {
return errors.New("multitrans: no session")
}
return c.openTalkChannel(uri, session)
}
func (c *Client) openTalkChannel(uri, session string) error {
payload := `{"type":"request","seq":0,"params":{"method":"get","talk":{"mode":"full_duplex"}}}`
data := fmt.Sprintf("MULTITRANS %s RTSP/1.0\r\nCSeq: 2\r\nSession: %s\r\nContent-Type: application/json\r\nContent-Length: %d\r\n\r\n%s",
uri, session, len(payload), payload)
if _, err := c.conn.Write([]byte(data)); err != nil {View on GitHub (pinned to c245815e75)