{"id":"5f86dbb4576f2c80","repo":"curl/curl","slug":"curl-multi-waitfds-failed-code-d","errorCode":null,"errorMessage":"curl_multi_waitfds() failed, code %d.\n","messagePattern":"curl_multi_waitfds\\(\\) failed, code (.+?)\\.\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"docs/libcurl/curl_multi_waitfds.md","lineNumber":79,"sourceCode":"#include <stdlib.h>\n\nint main(void)\n{\n  CURLMcode mresult;\n  struct curl_waitfd *ufds;\n\n  CURLM *multi = curl_multi_init();\n\n  do {\n    /* call curl_multi_perform() */\n\n    /* get the count of file descriptors from the transfers */\n    unsigned int fd_count = 0;\n\n    mresult = curl_multi_waitfds(multi, NULL, 0, &fd_count);\n\n    if(mresult != CURLM_OK) {\n      fprintf(stderr, \"curl_multi_waitfds() failed, code %d.\\n\", mresult);\n      break;\n    }\n\n    if(!fd_count)\n      continue; /* no descriptors yet */\n\n    /* allocate storage for our descriptors */\n    ufds = malloc(fd_count * sizeof(struct curl_waitfd));\n\n    /* get wait descriptors from the transfers and put them into array. */\n    mresult = curl_multi_waitfds(multi, ufds, fd_count, &fd_count);\n\n    if(mresult != CURLM_OK) {\n      fprintf(stderr, \"curl_multi_waitfds() failed, code %d.\\n\", mresult);\n      free(ufds);\n      break;\n    }\n","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/curl/curl/blob/527573490eb2564b3d7c9dd51d8bff963b5d6303/docs/libcurl/curl_multi_waitfds.md#L61-L97","documentation":"Printed in the curl_multi_waitfds example on the first (probe) call curl_multi_waitfds(multi, NULL, 0, &fd_count), which is the documented way to discover how many descriptors the multi handle uses before allocating storage. A non-zero CURLMcode means even this size query failed. The %d is the CURLMcode. curl_multi_waitfds was added in libcurl 8.8.0.","triggerScenarios":"curl_multi_waitfds(multi, NULL, 0, &fd_count) returns CURLM_BAD_HANDLE (1) when multi is NULL, freed, or not a CURLM handle; CURLM_OUT_OF_MEMORY (3); or CURLM_INTERNAL_ERROR (4). Because size=0 is explicitly the supported probe path, an OUT_OF_MEMORY here indicates genuine memory pressure rather than a too-small buffer.","commonSituations":"Calling curl_multi_waitfds on a libcurl older than 8.8.0 where the symbol is absent (link-time or runtime symbol error, not a CURLMcode but worth checking); passing a handle before curl_multi_init or after curl_multi_cleanup; running under severe memory pressure; calling from within a callback (CURLM_RECURSIVE_API_CALL).","solutions":["Check libcurl version at build/run time (need >= 8.8.0) since curl_multi_waitfds did not exist before then.","Verify curl_multi_init() returned a valid, non-NULL CURLM* and that it has not been cleaned up.","Ensure the call is not made from inside a libcurl callback (CURLM_RECURSIVE_API_CALL).","On CURLM_OUT_OF_MEMORY, investigate overall process memory; on CURLM_INTERNAL_ERROR, upgrade libcurl and report the bug."],"exampleFix":"// before\nmresult = curl_multi_waitfds(multi, NULL, 0, &fd_count);\nif(mresult != CURLM_OK) {\n  fprintf(stderr, \"curl_multi_waitfds() failed, code %d.\\n\", mresult);\n  break;\n}\n\n// after - guard handle and version, report symbolically\nif(!multi) { fprintf(stderr, \"multi handle is NULL\\n\"); break; }\nmresult = curl_multi_waitfds(multi, NULL, 0, &fd_count);\nif(mresult != CURLM_OK) {\n  fprintf(stderr, \"curl_multi_waitfds() probe failed: %s (%d)\\n\",\n          curl_multi_strerror(mresult), mresult);\n  break;\n}","handlingStrategy":"validation","validationCode":"// First call: query the descriptor count with a NULL buffer.\nif (multi == NULL) { return -1; }\nunsigned int fd_count = 0;\n/* size == 0 is the documented way to ask for the count. */\nCURLMcode q = curl_multi_waitfds(multi, NULL, 0, &fd_count);\nif (q != CURLM_OK || fd_count == 0) { /* nothing to wait on yet */ }","typeGuard":"// Validate the count probe before allocating.\nstatic bool fd_count_usable(unsigned int n) {\n    return n > 0 && n < (1024u * 1024u); /* sanity ceiling against runaway */\n}","tryCatchPattern":"mresult = curl_multi_waitfds(multi, NULL, 0, &fd_count);\nif (mresult != CURLM_OK) {\n    fprintf(stderr, \"curl_multi_waitfds() failed, code %d.\\n\", (int)mresult);\n    break;\n}","preventionTips":["Call curl_multi_waitfds once with size 0 to learn fd_count before allocating any buffer.","Guard the multi handle for NULL; CURLM_BAD_HANDLE is returned otherwise.","Treat fd_count == 0 as 'no descriptors yet', not an error: continue the loop.","Size your allocation to at least fd_count; passing a smaller size triggers CURLM_OUT_OF_MEMORY."],"tags":["libcurl","curl-multi","waitfds","poll","version","c"],"analyzedSha":"527573490eb2564b3d7c9dd51d8bff963b5d6303","analyzedAt":"2026-08-01T21:00:26.351Z","schemaVersion":2}