{"record":{"id":"02833acf6dfab1da","repo":"AlexxIT/go2rtc","slug":"multitrans-no-session","errorCode":null,"errorMessage":"multitrans: no session","messagePattern":"multitrans: no session","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/multitrans/client.go","lineNumber":158,"sourceCode":"\t\turi, authHeader, uid)\n\n\tif _, err = c.conn.Write([]byte(data)); err != nil {\n\t\treturn err\n\t}\n\n\tres, err = tcp.ReadResponse(c.rd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif res.StatusCode != http.StatusOK {\n\t\treturn errors.New(\"multitrans: auth failed: \" + res.Status)\n\t}\n\n\t// Session: 7116520596809429228\n\tsession := res.Header.Get(\"Session\")\n\tif session == \"\" {\n\t\treturn errors.New(\"multitrans: no session\")\n\t}\n\n\treturn c.openTalkChannel(uri, session)\n}\n\nfunc (c *Client) openTalkChannel(uri, session string) error {\n\tpayload := `{\"type\":\"request\",\"seq\":0,\"params\":{\"method\":\"get\",\"talk\":{\"mode\":\"full_duplex\"}}}`\n\n\tdata := 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\",\n\t\turi, session, len(payload), payload)\n\n\tif _, err := c.conn.Write([]byte(data)); err != nil {\n\t\treturn err\n\t}\n\n\tres, err := tcp.ReadResponse(c.rd)\n\tif err != nil {\n\t\treturn err","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/AlexxIT/go2rtc/blob/c245815e75e2a5fd60b4290f12bfc04e55a984d3/pkg/multitrans/client.go#L140-L176","documentation":"After a successful (200) digest-auth response, the multitrans handshake expects an HTTP 'Session' header carrying the session ID. If the header is missing the client cannot open the talk channel, so it fails with this error. It indicates a device that authenticated but did not return the session token the protocol requires.","triggerScenarios":"Calling Dial; handshake receives 200 OK but res.Header.Get(\"Session\") is empty, then openTalkChannel is skipped and the error is returned.","commonSituations":"Firmware that omits the Session header or renames it; an intermediate proxy stripping custom headers; device at an unsupported firmware version.","solutions":["Update the device firmware to a version that returns the Session header on successful auth.","Bypass proxies/load balancers that may strip non-standard headers like Session.","Capture the handshake with a packet sniffer to confirm whether the header is present on the wire.","Retry Dial; some devices intermittently omit the header under load."],"exampleFix":"// before\nres, _ := http.Get(proxyURL + \"/device/talk\") // proxy may strip Session\n\n// after\nres, _ := http.Get(\"http://\" + deviceHost + \"/device/talk\") // talk directly to device","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := client.Dial(ctx); err != nil {\n    if strings.Contains(err.Error(), \"no session\") {\n        // device firmware issue; fall back to RTSP/snapshot API instead of talk\n        return useRTSPFallback(ctx, device)\n    }\n    return err\n}","preventionTips":["Pin/verify firmware versions known to return the Session header.","Bypass header-stripping proxies for camera control traffic.","Capture one successful handshake with Wireshark as a golden reference.","Retry once before giving up — some devices intermittently omit the header."],"tags":["http","session","handshake","missing-header"],"backgroundTag":"empty-required-field","analyzedSha":"c245815e75e2a5fd60b4290f12bfc04e55a984d3","analyzedAt":"2026-09-07T11:47:02.965Z","contentChangedAt":"2026-09-07T11:47:02.965Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}