curl/curl ยท error

curl_easy_perform() failed: %s

Error message

curl_easy_perform() failed: %s

What it means

This error is reported in the IMAP NOOP example when curl_easy_perform() fails after sending the custom command 'NOOP'. NOOP is intentionally a no-op used to keep the session alive and collect server status updates; because it does nothing, a failure almost always indicates a session-level problem (connection, TLS, or authentication) rather than anything intrinsic to NOOP itself.

Source

Thrown at docs/examples/imap-noop.c:63

  curl = curl_easy_init();
  if(curl) {
    /* Set username and password */
    curl_easy_setopt(curl, CURLOPT_USERNAME, "user");
    curl_easy_setopt(curl, CURLOPT_PASSWORD, "secret");

    /* This is the server URL */
    curl_easy_setopt(curl, CURLOPT_URL, "imap://imap.example.com");

    /* Set the NOOP command */
    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "NOOP");

    /* Perform the custom request */
    result = curl_easy_perform(curl);

    /* Check for errors */
    if(result != CURLE_OK)
      fprintf(stderr, "curl_easy_perform() failed: %s\n",
              curl_easy_strerror(result));

    /* Always cleanup */
    curl_easy_cleanup(curl);
  }

  curl_global_cleanup();

  return (int)result;
}

View on GitHub (pinned to 527573490e)

Solutions

  1. Replace placeholder host and credentials with real values.
  2. Switch to imaps:// with CURLOPT_USE_SSL=CURLUSESSL_ALL for TLS-only servers.
  3. For keep-alive use, send NOOP more frequently than the server's idle timeout, or use the IMAP IDLE extension instead.
  4. Confirm network reachability to port 143/993 and that 'curl -V' includes imap/imaps.
  5. Handle CURLE_RECV_ERROR / CURLE_OPERATION_TIMEDOUT by re-establishing the session.

Example fix

// before
curl_easy_setopt(curl, CURLOPT_URL, "imap://imap.example.com");
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "NOOP");
result = curl_easy_perform(curl);
if(result != CURLE_OK)
  fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(result));

// after
curl_easy_setopt(curl, CURLOPT_URL, "imaps://imap.example.com");
curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL);
curl_easy_setopt(curl, CURLOPT_USERNAME, REAL_USER);
curl_easy_setopt(curl, CURLOPT_PASSWORD, REAL_PASS);
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "NOOP");
result = curl_easy_perform(curl);
if(result != CURLE_OK)
  fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(result));
Defensive patterns

Strategy: try-catch

Validate before calling

/* imap-noop.c: NOOP is cheap but still needs a reachable host + valid cmd */
#include <string.h>
CURLcode validate_noop_request(const char *url, const char *custom) {
  if(!url || strncmp(url, "imap", 4) != 0)
    return CURLE_URL_MALFORMAT;
  const char *host = url + 4;
  if(strncmp(host, "://", 3) == 0) host += 3; else return CURLE_URL_MALFORMAT;
  if(*host == '\0' || *host == '/')
    return CURLE_URL_MALFORMAT;
  if(!custom || strcmp(custom, "NOOP") != 0)
    return CURLE_BAD_FUNCTION_ARGUMENT;
  return CURLE_OK;
}

Type guard

/* NOOP failure is essentially a connection liveness signal */
#include <curl/curl.h>
static int noop_connection_lost(CURLcode rc) {
  return rc == CURLE_COULDNT_CONNECT
      || rc == CURLE_OPERATION_TIMEDOUT
      || rc == CURLE_RECV_ERROR
      || rc == CURLE_PARTIAL_FILE;
}

Try / catch

/* NOOP: use the result as a keep-alive probe; reconnect on connection loss */
result = curl_easy_perform(curl);
if(result != CURLE_OK) {
  if(noop_connection_lost(result)) {
    fprintf(stderr, "Connection lost during NOOP; tearing down\n");
    curl_easy_cleanup(curl);
    curl = rebuild_session();            /* reconnect + re-authenticate */
  } else {
    fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(result));
  }
}
curl_easy_cleanup(curl);

Prevention

When it happens

Trigger: curl_easy_perform() fails with CURLOPT_URL "imap://imap.example.com" and CURLOPT_CUSTOMREQUEST "NOOP". Typical causes: wrong credentials (CURLE_LOGIN_DENIED), connection refused/timeout (CURLE_COULDNT_CONNECT / CURLE_OPERATION_TIMEDOUT), server closed the idle connection before NOOP was sent (CURLE_RECV_ERROR), or the server requires TLS so plaintext imap:// is rejected.

Common situations: Developers use NOOP as a keep-alive but the server enforces a short idle timeout and closes the socket; the placeholder host imap.example.com does not resolve; placeholder credentials 'user'/'secret' are left in place; corporate IMAP requires imaps:// on 993; the example is run in an environment that blocks outbound port 143.

Related errors


AI-assisted analysis of curl/curl@527573490e (2026-08-01). Data as JSON: /data/errors/c5ecd945795e580a.json. Report an issue: GitHub.