{"record":{"id":"20f27cc6642ff616","repo":"cloudflare/cloudflared","slug":"failed-to-unmarshal-quick-tunnel","errorCode":null,"errorMessage":"failed to unmarshal quick Tunnel","messagePattern":"failed to unmarshal quick Tunnel","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/cloudflared/tunnel/quick_tunnel.go","lineNumber":96,"sourceCode":"\trespBody, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"failed to read quick-tunnel response\")\n\t}\n\n\tif resp.StatusCode < 200 || resp.StatusCode >= 300 {\n\t\tvar data QuickTunnelResponse\n\t\tif err := json.Unmarshal(respBody, &data); err == nil && len(data.Errors) > 0 {\n\t\t\treturn fmt.Errorf(\"quick tunnel provisioning failed with status %d: %s\", resp.StatusCode, formatQuickTunnelErrors(data.Errors))\n\t\t}\n\t\treturn fmt.Errorf(\"quick tunnel provisioning failed with status %d: %s\", resp.StatusCode, string(respBody))\n\t}\n\n\tvar data QuickTunnelResponse\n\tif err := json.Unmarshal(respBody, &data); err != nil {\n\t\trespString := string(respBody)\n\t\tfields := map[string]interface{}{\"status_code\": resp.Status}\n\t\tsc.log.Err(err).Fields(fields).Msgf(\"Error unmarshaling QuickTunnel response: %s\", respString)\n\t\treturn errors.Wrap(err, \"failed to unmarshal quick Tunnel\")\n\t}\n\n\t// TODO(TUN-10791): Add CLI-level coverage that provisioning errors are logged to users.\n\tif len(data.Errors) > 0 {\n\t\treturn fmt.Errorf(\"quick tunnel provisioning failed: %s\", formatQuickTunnelErrors(data.Errors))\n\t}\n\n\tif !data.Success {\n\t\treturn errors.New(\"quick tunnel provisioning failed\")\n\t}\n\n\ttunnelID, err := uuid.Parse(data.Result.ID)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"failed to parse quick Tunnel ID\")\n\t}\n\n\tcredentials := connection.Credentials{\n\t\tAccountTag:   data.Result.AccountTag,","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/cmd/cloudflared/tunnel/quick_tunnel.go#L78-L114","documentation":"The quick-tunnel service returned a body that could not be parsed as JSON (QuickTunnelResponse). cloudflared logs the raw body and status, then returns this wrapped error. It means the API replied something other than the expected JSON schema.","triggerScenarios":"json.Unmarshal(respBody, &data) fails after a successful HTTP response from the quick-service endpoint.","commonSituations":"Captive portals or proxies returning HTML error/login pages instead of JSON; an outdated cloudflared talking to a changed API; custom quick-service endpoints that return different payloads.","solutions":["Check the logged 'Error unmarshaling QuickTunnel response' line to see the raw body (often an HTML captive-portal page)","Complete captive-portal/Wi-Fi login or bypass the intercepting proxy and retry","Upgrade cloudflared to the latest version to match current API response schema","If using a custom quick-service, verify it returns the Cloudflare QuickTunnelResponse JSON shape"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"ct := resp.Header.Get(\"Content-Type\")\nif !strings.Contains(ct, \"application/json\") {\n    return fmt.Errorf(\"quick-tunnel returned non-JSON content type %q (captive portal/proxy?)\", ct)\n}","typeGuard":null,"tryCatchPattern":"if err := json.Unmarshal(respBody, &data); err != nil {\n    log.Printf(\"quick-tunnel non-JSON response (%d): %s\", resp.StatusCode, string(respBody))\n    return err\n}","preventionTips":["Complete captive-portal logins before running","Exclude cloudflared endpoints from TLS-intercepting proxies","Pin a supported cloudflared version"],"tags":["go","json","http","api"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f","analyzedAt":"2026-09-06T04:14:33.757Z","contentChangedAt":"2026-09-06T04:14:33.757Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}