curl/curl ยท error

curl_easy_perform() failed: %s

Error message

curl_easy_perform() failed: %s

What it means

Printed when curl_easy_perform() fails for a POP3 UIDL custom request (lists messages by unique ID). Like STAT/NOOP the UIDL response is delivered through the command channel; this example does not set CURLOPT_NOBODY, so any failure in connect/auth/UIDL surfaces here. The %s expands to curl_easy_strerror of the returned CURLcode.

Source

Thrown at docs/examples/pop3-uidl.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, "pop3://pop.example.com");

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

    /* 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. Decode the appended CURLcode: QUOTE_ERROR -> UIDL rejected/unsupported; LOGIN_DENIED -> credentials; COULDNT_CONNECT -> network/port.
  2. Check CAPA via CURLOPT_VERBOSE to confirm the server advertises UIDL before relying on it.
  3. Verify host reachability on port 110 and the USER/PASS credentials.
  4. Ensure CURLOPT_CUSTOMREQUEST is set to the exact string 'UIDL' (or 'UIDL <n>' for a single message).
  5. Add CURLOPT_USE_SSL = CURLUSESSL_ALL if the server requires encryption before authentication.

Example fix

// before
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "UIDL");
result = curl_easy_perform(curl);
if(result != CURLE_OK)
  fprintf(stderr, "curl_easy_perform() failed: %s\n",
          curl_easy_strerror(result));

// after: confirm CAPA support, use TLS, and log the exchange
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "UIDL");
curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
result = curl_easy_perform(curl);
Defensive patterns

Strategy: try-catch

Validate before calling

CURL *h = curl_easy_init();
if (!h) return 1;
if (curl_easy_setopt(h, CURLOPT_URL, url) != CURLE_OK) { curl_easy_cleanup(h); return 1; }

Type guard

static int is_valid_easy_handle(CURL *h) {
  return h != NULL;
}

Try / catch

CURLcode res = curl_easy_perform(h);
if (res != CURLE_OK) {
  fprintf(stderr, "pop3-uidl failed: %s\n", curl_easy_strerror(res));
}
curl_easy_cleanup(h);

Prevention

When it happens

Trigger: Triggered on line 59 of pop3-uidl.c when the UIDL custom request fails. Typical codes: CURLE_COULDNT_CONNECT (port 110), CURLE_LOGIN_DENIED (bad credentials), CURLE_QUOTE_ERROR / CURLE_RECV_ERROR (server returns -ERR to UIDL, or UIDL unsupported per RFC 2449 CAPA), CURLE_PARTIAL_FILE if the listing is truncated mid-stream.

Common situations: Server that does not implement UIDL (older or minimal POP3), placeholder pop.example.com never resolves, wrong credentials, network egress blocking POP3, or accidental removal of CURLOPT_CUSTOMREQUEST causing a default LIST instead of UIDL.

Related errors


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