ERR_GET_ERROR(3)

πŸ“¦ version 4.4.0, in alpine 3.24, arch rolling

πŸ’… ERR_GET_ERROR(3) β€” the OpenSSL error-queue page, but make it make sense

okay so this is a page from the Library Functions Manual (the 3 section, bestie β€” library functions, not syscalls, not commands) and it's all about pulling error codes and their extra data out of OpenSSL's error queue. It's ERR_GET_ERROR and it's giving "I have so many questions about why my TLS handshake failed" energy. Let's go ✨


🌸 NAME 🌸

ERR_get_error, ERR_peek_error, ERR_peek_last_error, ERR_get_error_line, ERR_peek_error_line, ERR_peek_last_error_line, ERR_get_error_line_data, ERR_peek_error_line_data, ERR_peek_last_error_line_data β€” obtain OpenSSL error code and data πŸŽ€

That's nine whole functions, yes, and they all do basically the same thing but with slightly different vibes. Stay with me.


✨ SYNOPSIS ✨

so first off, this lives in the library "libcrypto" and you get at it with:

#include <openssl/err.h>

and here's the whole squad, exactly as declared:

unsigned long
ERR_get_error(void);

unsigned long
ERR_peek_error(void);

unsigned long
ERR_peek_last_error(void);

unsigned long
ERR_get_error_line(const char **file, int *line);

unsigned long
ERR_peek_error_line(const char **file, int *line);

unsigned long
ERR_peek_last_error_line(const char **file, int *line);

unsigned long
ERR_get_error_line_data(const char **file, int *line, const char **data,
    int *flags);

unsigned long
ERR_peek_error_line_data(const char **file, int *line,
    const char **data, int *flags);

unsigned long
ERR_peek_last_error_line_data(const char **file, int *line,
    const char **data, int *flags);

every single one returns unsigned long, which is the error code. iconique. πŸ‘‘


πŸ¦‹ DESCRIPTION πŸ¦‹

okay so the mental model here is: each thread has its own little error queue, and these functions are how you read from it. Two things to keep straight β€” which end you're reading from, and whether you take the entry or just look at it.

  • ERR_get_error() β€” returns the earliest error code from the thread's error queue and removes the entry. So it's destructive, kind of. You can call it over and over until there are no more error codes left to return. Drain the queue, bestie. πŸ«—
  • ERR_peek_error() β€” returns the earliest error code from the thread's error queue without modifying it. Peek, don't touch. πŸ™ˆ
  • ERR_peek_last_error() β€” returns the latest error code from the thread's error queue without modifying it. Note that's latest, not earliest β€” different end of the queue, no cap.
also, if you actually want to understand the error code you just got, that's not this page. see ERR_GET_LIB(3) for info about the location and reason for the error, and ERR_error_string(3) for human-readable error messages. this page is just the vending machine. πŸ’…

πŸŽ€ the _line girlies

  • ERR_get_error_line(), ERR_peek_error_line(), and ERR_peek_last_error_line() are the same as the above, but they additionally store the file name and line number where the error occurred in *file and *line β€” unless those are NULL, in which case they're just skipped. so you get the receipts: where it happened. 🧾

πŸ“ the _line_data girlies (yes there's more)

  • ERR_get_error_line_data(), ERR_peek_error_line_data(), and ERR_peek_last_error_line_data() store additional data and flags associated with the error code in *data and *flags, unless those are NULL. And here's the detail: *data contains a string if *flags&ERR_TXT_STRING is true. that's the check, don't skip it. πŸ”

⭐ the one rule, do NOT mess this up ⭐

An application MUST NOT free the *data pointer (or any other pointers returned by these functions) with free(3) β€” freeing is handled automatically by the error library. 🚨

fr fr. do not free(3) that pointer. it is not yours to free. the error library handles it. if you free it yourself you will have a bad time and I will be sad. 😭


πŸ’œ RETURN VALUES πŸ’œ

  • The error code β€” or 0 if there is no error in the queue.

that's it. 0 means the queue is empty, bestie, congratulations, nothing is wrong (or nothing is recorded as wrong, which is a different thing, but that's not this page's problem ✨).


🌈 SEE ALSO 🌈

go read those next, iykyk 🫢


πŸ‘‘ HISTORY πŸ‘‘

the lore is long and honestly kind of impressive:

  • ERR_get_error() and ERR_peek_error() first appeared in SSLeay 0.4.4.
  • ERR_get_error_line() and ERR_peek_error_line() first appeared in SSLeay 0.6.0.
  • ERR_get_error_line_data() and ERR_peek_error_line_data() first appeared in SSLeay 0.9.0.
  • All these functions have been available since OpenBSD 2.4.

and then the peek_last trio showed up fashionably late:

  • ERR_peek_last_error(), ERR_peek_last_error_line(), and ERR_peek_last_error_line_data() first appeared in OpenSSL 0.9.7 and have been available since OpenBSD 3.2.

main character energy for a function that just looks at the back of a queue, honestly. πŸ’€


🧚 sign-off 🧚

this page is from the Debian build of the manual, dated June 8, 2025, and it lives at section ERR_GET_ERROR(3). so if you're citing it in a bug report or a group chat, that's your source, bestie. now go drain that error queue πŸ’–πŸŒΈβœ¨

πŸ“¦ where this page comes from