AlexxIT/go2rtc · error
err.Error()
Error message
err.Error()
What it means
When Content-Type is application/json, outputWebRTC decodes the request body into a pion.SessionDescription. If the body is not valid JSON (or not shaped like a session description), json.Decode fails and the handler logs the error and returns HTTP 400 with the decoder's error text. This guards the JSON SDP-exchange path against malformed payloads.
Solutions
- Send the body as {"type":"offer","sdp":"<full SDP>"} when using Content-Type: application/json
- Or drop the JSON Content-Type and send raw SDP (application/sdp) so the default branch reads the body
- Validate the JSON body client-side before sending
Example fix
// before
fetch(url, {method:'POST', headers:{'Content-Type':'application/json'}, body: pc.localDescription.sdp})
// after
fetch(url, {method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify(pc.localDescription)}) Defensive patterns
Strategy: validation
Validate before calling
const payload = {type: pc.localDescription.type, sdp: pc.localDescription.sdp};
JSON.parse(JSON.stringify(payload)); // throws early if not serializable
if (!payload.sdp?.startsWith('v=0')) throw new Error('invalid SDP'); Type guard
const isSessionDescription = (d) => d && typeof d.sdp === 'string' && d.sdp.startsWith('v=0'); Try / catch
try { ... } catch (e) { if (e.response?.status === 400) { console.error('Body must be valid JSON SessionDescription'); } } Prevention
- Always JSON.stringify the full localDescription, not just the sdp string
- Match Content-Type to the actual payload format
- Add a client-side sanity check that the SDP starts with 'v=0'
When it happens
Trigger: POST with Content-Type: application/json but body is raw SDP text instead of {"type":"offer","sdp":"v=0\r\n..."}; truncated body; sending SDP with the JSON content type; invalid JSON syntax.
Common situations: Clients that read the SDP from a file and forget to wrap it in the JSON envelope; copy-paste errors adding trailing text; a fetch() call whose body was serialized twice or not at all.
Related errors
AI-assisted analysis of AlexxIT/go2rtc@c245815e75 (2026-09-07).
Data as JSON: /api/errors/4e2d8d7e7e1424ab.
Report an issue: GitHub.
Appendix: source
Thrown at internal/webrtc/server.go:86
if stream == nil {
http.Error(w, api.StreamNotFound, http.StatusNotFound)
return
}
mediaType := r.Header.Get("Content-Type")
if mediaType != "" {
mediaType, _, _ = strings.Cut(mediaType, ";")
mediaType = strings.ToLower(strings.TrimSpace(mediaType))
}
var offer string
switch mediaType {
case "application/json":
var desc pion.SessionDescription
if err := json.NewDecoder(r.Body).Decode(&desc); err != nil {
log.Error().Err(err).Caller().Send()
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
offer = desc.SDP
case "application/x-www-form-urlencoded":
if err := r.ParseForm(); err != nil {
log.Error().Err(err).Caller().Send()
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
offerB64 := r.Form.Get("data")
b, err := base64.StdEncoding.DecodeString(offerB64)
if err != nil {
log.Error().Err(err).Caller().Send()
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
offer = string(b)View on GitHub (pinned to c245815e75)