{"id":"1f1e68a154ad034e","repo":"curl/curl","slug":"curl-easy-perform-failed-s-1f1e68","errorCode":null,"errorMessage":"curl_easy_perform() failed: %s\n","messagePattern":"curl_easy_perform\\(\\) failed: (.+?)\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"docs/examples/websocket-updown.c","lineNumber":120,"sourceCode":"      curl_easy_setopt(curl, CURLOPT_URL, argv[1]);\n    else\n      curl_easy_setopt(curl, CURLOPT_URL, \"wss://example.com\");\n\n    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);\n    curl_easy_setopt(curl, CURLOPT_WRITEDATA, curl);\n    curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_cb);\n    /* tell curl that we want to send the payload */\n    rctx.curl = curl;\n    rctx.blen = sizeof(payload) - 1;\n    memcpy(rctx.buf, payload, rctx.blen);\n    curl_easy_setopt(curl, CURLOPT_READDATA, &rctx);\n    curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);\n\n    /* Perform the request, result gets the return code */\n    result = curl_easy_perform(curl);\n    /* Check for errors */\n    if(result != CURLE_OK)\n      fprintf(stderr, \"curl_easy_perform() failed: %s\\n\",\n              curl_easy_strerror(result));\n\n    /* always cleanup */\n    curl_easy_cleanup(curl);\n  }\n  curl_global_cleanup();\n  return (int)result;\n}\n","sourceCodeStart":102,"sourceCodeEnd":129,"githubUrl":"https://github.com/curl/curl/blob/527573490eb2564b3d7c9dd51d8bff963b5d6303/docs/examples/websocket-updown.c#L102-L129","documentation":"Generic failure report from curl_easy_perform() in the websocket-updown example; result holds the CURLcode returned by the transfer. The message just renders curl_easy_strerror(result), so the underlying cause is whatever made the full WebSocket upload+download transfer fail.","triggerScenarios":"Emitted at the end of main() when curl_easy_perform(curl) returns non-CURLE_OK for the wss:// upload/download transfer that has read_cb (upload) and write_cb (download) attached.","commonSituations":"DNS/TCP/TLS connection failures, invalid or unreachable ws/wss URL, server rejecting the WebSocket upgrade, expired/bad TLS certificates, proxy misconfiguration, timeouts, or a libcurl build without WebSocket support.","solutions":["Read the rendered curl_easy_strerror text (e.g. 'Couldn\\'t connect to server', 'SSL peer certificate...') to narrow the cause.","Verify the wss:// URL resolves and that the endpoint supports WebSocket (expect HTTP 101 on upgrade).","Check TLS: set CURLOPT_CAINFO to a valid CA bundle or fix the server certificate; confirm CURLOPT_SSL_VERIFYPEER behavior.","Enable CURLOPT_VERBOSE to log the handshake and identify where the transfer aborts.","Ensure the libcurl in use was built with WebSocket support."],"exampleFix":"// before\nresult = curl_easy_perform(curl);\nif(result != CURLE_OK)\n  fprintf(stderr, \"curl_easy_perform() failed: %s\\n\", curl_easy_strerror(result));\n// after\ncurl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);\nresult = curl_easy_perform(curl);\nif(result != CURLE_OK)\n  fprintf(stderr, \"curl_easy_perform() failed: %s\\n\", curl_easy_strerror(result));","handlingStrategy":"retry","validationCode":"/* Pre-flight removes the argument/config class of failures.\n   Transient network failures are still handled by the retry loop. */\nstatic CURLcode ws_perform_preflight(CURL *curl, const char *url) {\n  if(curl == NULL) return CURLE_BAD_FUNCTION_ARGUMENT;\n  if(url == NULL)  return CURLE_URL_MALFORMAT;\n  if(strncmp(url, \"ws://\", 5) && strncmp(url, \"wss://\", 6))\n      return CURLE_UNSUPPORTED_PROTOCOL;\n  return CURLE_OK;\n}","typeGuard":"/* Narrow a CURLcode into an actionable bucket; drives retry policy. */\nenum curl_kind { K_OK, K_TRANSIENT, K_PERMANENT };\nstatic enum curl_kind curlcode_classify(CURLcode c) {\n  switch(c) {\n    case CURLE_OK:                       return K_OK;\n    case CURLE_COULDNT_RESOLVE_HOST:\n    case CURLE_COULDNT_RESOLVE_PROXY:\n    case CURLE_COULDNT_CONNECT:\n    case CURLE_WEIRD_SERVER_REPLY:\n    case CURLE_OPERATION_TIMEDOUT:\n    case CURLE_GOT_NOTHING:\n    case CURLE_SEND_ERROR:\n    case CURLE_RECV_ERROR:\n    case CURLE_PARTIAL_FILE:\n    case CURLE_HTTP2_STREAM:\n    case CURLE_AGAIN:                    return K_TRANSIENT;\n    default:                             return K_PERMANENT;\n  }\n}","tryCatchPattern":"CURLcode r;\nfor(unsigned attempt = 0; attempt < MAX_ATTEMPTS; ++attempt) {\n    r = curl_easy_perform(curl);\n    if(curlcode_classify(r) != K_TRANSIENT) break;   /* OK or permanent */\n    backoff_sleep(attempt);                           /* exp backoff + jitter */\n}\nif(r != CURLE_OK)\n    fprintf(stderr, \"curl_easy_perform() failed: %s\\n\", curl_easy_strerror(r));","preventionTips":["Set CURLOPT_CONNECTTIMEOUT and CURLOPT_TIMEOUT so transient stalls surface as classifiable codes.","Validate the ws/wss URL and handle before perform to eliminate argument-class errors.","Bound the retry count and use exponential backoff with jitter.","Do not retry permanent codes (e.g. CURLE_URL_MALFORMAT, CURLE_SSL_CONNECT_ERROR).","Enable CURLOPT_NOSIGNAL on systems using multi-threaded timeouts."],"tags":["libcurl","websocket","network","transfer","curl-easy-perform"],"analyzedSha":"527573490eb2564b3d7c9dd51d8bff963b5d6303","analyzedAt":"2026-08-01T21:00:26.351Z","schemaVersion":2}