{"record":{"id":"bc482537cb416bdb","repo":"tailscale/tailscale","slug":"decoding-register-response-w","errorCode":null,"errorMessage":"decoding register response: %w","messagePattern":"decoding register response: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"control/tsp/register.go","lineNumber":110,"sourceCode":"\n\tif res.StatusCode != 200 {\n\t\tmsg, _ := io.ReadAll(io.LimitReader(res.Body, maxResponseSize))\n\t\treturn nil, fmt.Errorf(\"register request: http %d: %.200s\",\n\t\t\tres.StatusCode, strings.TrimSpace(string(msg)))\n\t}\n\n\t// Read up to maxResponseSize+1 so we can distinguish \"exactly at cap\" from\n\t// \"over the cap\" rather than relying on a truncated json parse error.\n\tdata, err := io.ReadAll(io.LimitReader(res.Body, maxResponseSize+1))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"reading register response: %w\", err)\n\t}\n\tif int64(len(data)) > maxResponseSize {\n\t\treturn nil, fmt.Errorf(\"register response exceeds max %d\", maxResponseSize)\n\t}\n\tvar resp tailcfg.RegisterResponse\n\tif err := json.Unmarshal(data, &resp); err != nil {\n\t\treturn nil, fmt.Errorf(\"decoding register response: %w\", err)\n\t}\n\tif resp.Error != \"\" {\n\t\treturn nil, fmt.Errorf(\"register: %s\", resp.Error)\n\t}\n\treturn &resp, nil\n}\n","sourceCodeStart":92,"sourceCodeEnd":117,"githubUrl":"https://github.com/tailscale/tailscale/blob/6e0912f97994f927632b34ae9e63b53d6516a6ac/control/tsp/register.go#L92-L117","documentation":"The 200 body is not valid JSON for tailcfg.RegisterResponse: json.Unmarshal failed after transport and size checks passed. The content is wrong rather than unreachable: typically an HTML error page, an empty body, or output from an incompatible server version.","triggerScenarios":"A proxy or CDN intercepting and rewriting the response; a control server speaking a different schema; a body mangled or truncated in transit.","commonSituations":"TLS-intercepting middleboxes; ingress returning 200 with an error page; version skew with a forked control server.","solutions":["Log the raw body before Unmarshal in a debug build to see what actually arrived","Remove or fix middleboxes between client and control server","Verify the server implements the register protocol version this client expects"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err != nil {\n    var syn *json.SyntaxError\n    if errors.As(err, &syn) {\n        // body was not JSON: inspect what the server or proxy actually returned\n    }\n}","preventionTips":["Keep middleboxes from rewriting control-plane response bodies","Pin and verify server versions in the deployment so schema output is predictable"],"tags":["go","tsp","json","decoding","http-proxy"],"backgroundTag":"json-unmarshal-error","analyzedSha":"6e0912f97994f927632b34ae9e63b53d6516a6ac","analyzedAt":"2026-08-18T08:17:25.280Z","contentChangedAt":"2026-08-18T08:17:25.280Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}