curl/curl ยท error
error starting frame: %d
Error message
error starting frame: %d
What it means
Printed in the read callback of the websocket-updown example when curl_ws_start_frame() returns a non-CURLE_OK code on the callback's first invocation. curl_ws_start_frame() begins a new outbound WebSocket frame with the given flags (here CURLWS_TEXT) and payload length; failure means libcurl could not initiate the frame send on the current transfer. The callback then aborts the upload by returning CURL_READFUNC_ABORT.
Source
Thrown at docs/examples/websocket-updown.c:72
char buf[1024];
size_t blen;
size_t nsent;
};
static size_t read_cb(char *buf, size_t nitems, size_t buflen, void *p)
{
struct read_ctx *ctx = p;
size_t len = nitems * buflen;
size_t left = ctx->blen - ctx->nsent;
if(!ctx->nsent) {
CURLcode result;
/* On first call, set the FRAME information to be used (it defaults to
* CURLWS_BINARY otherwise). */
result = curl_ws_start_frame(ctx->curl, CURLWS_TEXT,
(curl_off_t)ctx->blen);
if(result != CURLE_OK) {
fprintf(stderr, "error starting frame: %d\n", (int)result);
return CURL_READFUNC_ABORT;
}
}
fprintf(stderr, "read(len=%d, left=%d)\n", (int)len, (int)left);
if(left) {
if(left < len)
len = left;
memcpy(buf, ctx->buf + ctx->nsent, len);
ctx->nsent += len;
return len;
}
return 0;
}
int main(int argc, const char *argv[])
{
CURL *curl;
struct read_ctx rctx;View on GitHub (pinned to 527573490e)
Solutions
- Use a ws:// or wss:// URL and ensure the server completes the WebSocket upgrade (HTTP 101) before the read callback runs.
- Verify the libcurl build supports WebSockets (curl --version shows 'WebSocket'); rebuild with --enable-websockets if missing.
- Confirm CURLOPT_UPLOAD is paired with a real WS transfer and that curl_ws_start_frame flags (CURLWS_TEXT/CURLWS_BINARY) and length are valid.
- Inspect the returned CURLcode int in the message against curl_easy_strerror() to identify the exact failure (e.g. CURLE_URL_MALFORMAT, CURLE_HTTP_RETURNED_ERROR).
Example fix
// before curl_easy_setopt(curl, CURLOPT_URL, "http://example.com"); curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); // after curl_easy_setopt(curl, CURLOPT_URL, "wss://echo.websocket.events"); curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
Defensive patterns
Strategy: validation
Validate before calling
static CURLcode ws_upload_preflight(CURL *curl, const char *url, size_t blen) {
if(curl == NULL) return CURLE_BAD_FUNCTION_ARGUMENT;
if(blen == 0) return CURLE_BAD_FUNCTION_ARGUMENT;
if(strncmp(url, "ws://", 5) && strncmp(url, "wss://", 6))
return CURLE_UNSUPPORTED_PROTOCOL;
CURLcode r = curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
return r; /* call before curl_easy_perform(); abort transfer if non-OK */
} Try / catch
/* inside the CURLOPT_READFUNCTION callback, on the first chunk: */
CURLcode r = curl_ws_start_frame(ctx->curl, CURLWS_TEXT, (curl_off_t)ctx->blen);
if(r != CURLE_OK) {
ctx->perform_result = r; /* surface to the curl_easy_perform caller */
return CURL_READFUNC_ABORT; /* abort the transfer cleanly */
} Prevention
- Initialize the easy handle with curl_easy_init() and verify it is non-NULL.
- Use only ws:// or wss:// URLs and set CURLOPT_UPLOAD before perform.
- Keep the payload length > 0 and <= CURL_MAX_WRITE_SIZE.
- Stash the callback's CURLcode so the caller reads it after curl_easy_perform instead of silently aborting.
When it happens
Trigger: Called inside read_cb() at the first chunk when CURLOPT_UPLOAD is set on a WebSocket (ws/wss) transfer and curl_ws_start_frame(curl, CURLWS_TEXT, blen) fails. Happens when the easy handle is not actually in a WebSocket send state, the connection upgrade never completed, CURLOPT_CONNECT_ONLY was mis-set, or the frame length/flags are rejected.
Common situations: Pointing the example at a plain http:// URL instead of ws/wss, setting CURLOPT_UPLOAD without a valid WebSocket connection, a server that rejected the WebSocket upgrade (no 101), or using a libcurl build compiled without WebSocket support.
Related errors
- ws: curl_ws_recv returned %u, received %u
- curl_easy_perform() failed: %s
- curl_easy_perform() failed: %s
- curl_easy_perform() failed: %s
- curl_easy_perform() failed: %s
AI-assisted analysis of curl/curl@527573490e (2026-08-01).
Data as JSON: /data/errors/6415e47c58cd8d43.json.
Report an issue: GitHub.