upvote
stacktraces? might also be useful to know whether or not the latest allocand was a jumbo sized allocand that caused the failure?
reply
Do you really want that data passed back down to the caller of the allocation? From the description of the failure state you'd want to log that data instead: what's the caller of the allocation going to do if you tell it it failed with a crazy size? It already knows the size, it's the one who asked for it.
reply
So, suppose it's a rust library -- you're locking me into whatever logging system the library author chooses? Maybe I'd like to consume the relevant data at the entry point and send it to a logging system of my choice.
reply
A Rust library likely wouldn't be returning an opaque Box<dyn Error> to begin with. Errors are part of a library's API—it's what allows consumers to handle them—so you'd define an enum of possible errors your library could produce and return that, which would be stored on the stack.
reply
What about the data in the error payload?
reply
I think this is a clash of terminology: a Rust enum isn't an integer with pretensions of an identity.

You'd describe it as a tagged union in some languages. So when you say you'd return an error with extra information, what that information is is associated with the specific variant of the enum.

Using yuriks AllocError as an example, if the error is SizeTooLarge, it has the size field. Other errors may have no additional data, others may have different data.

When you return an error from your allocating function, it's a known size, the size of the largest enum variant + the discriminant (tag).

reply
That's part of the error enum.

  enum AllocError {
    SizeTooLarge { size: usize },
    // etc.
  }
This enum has a known size and doesn't require any dynamic allocations.
reply
You can do better than the errors in other languages. You can provide all the relevant information in the emum variant.

  enum MyApiBindingCrateError {
    // You didn't provide an 
    // API key. Maybe we should 
    // design our interface to
    // make this impossible 
    ApiKeyMissing,

    // Client was unauthorized 
    // to make this request 
    AuthorizationError,

    // The entity you requested 
    // did not exist (404'd)
    NotFoundError,

    // You're sending too many 
    // requests to the server 
    TooManyRequests,

    // That specific error with
    // the API
    // Maybe users can't delete 
    // folders until they're empty 
    // Whatever 
    SpecificApiIssue1,

    // Some other specific error
    // with the API
    SpecificApiError2,
  
    // Server didn't respond the
    // way we expected. 
    // Here's what it told us
    UnexpectedHttpResponse { 
      // HTTP status code
      status_code: StatusCode, 

      // If it had a 
      // string-encoded body
      body: Option<String>,
    },

    // Unhandled Issue with IO 
    IoError(io::Error),
  
    // Unhandled Issue with 
    // request library
    ReqwestError(reqwest::Error),

  }
The beauty with Rust is that you can create really detailed concrete errors at the crate level. Your callers will know exactly what the actual error states are.

Your application can be a little less structured if you want. Though with LLMs, I'm using anyhow and thiserror a lot less.

reply
In the current context with regards to failed allocations, you're also supposed to add a variant that wraps AllocError.
reply
it depends, if the functionality represented by the library is known to require a lot of memory (or simply allocation failures are an expected part of its operation), then it should be pretty much part of the API, probably with some tracing/diagnostics interface to get the required visibility into how much memory goes and where.

but for most libraries I on allocation failure I don't expect any fancy logging system. maybe even panic is fine.

reply
usually “stdout” is good enough, wrapper/runner routes output to logserver for collation and search. who cares about formats as long as it’s reasonably structured and searchable?
reply
And how do you store a stacktrace without allocating?
reply
Any time I mention "but I would like stacktraces with my errors" I get told I'm doing it wrong.
reply
That's because the types of errors where you want a stack trace are a relatively small subset of all possible errors.

Stack traces are only useful for errors that indicate a bug in the program, i.e. something a programmers has to respond to. It's not useful for the vast class of bugs that are a result of wrong input, wrong external state, or infrastructure issues.

Rust projects tend to favor panicking over error handling for programmer bugs (which does indeed give you a stack trace depending on environment variables), or even better encoding the invariants in the type system, but there are cases where an error coming from a library are truly, actually unexpected, so both `anyhow` and `thiserror` do provide support for attaching a stack trace in those situations.

reply
See? You get people explaining to you that you actually don't want a stack trace because xyz.
reply
If you let the allocation error panic you will get your stack trace.

You can't have a stack trace on an error in the error path that failed to allocate. If you have a "jumbo sized" error and the error fails to allocate, it won't get reported. The only reporting you will get is that the error failed to allocate and this new allocation error overrides the error that failed to allocate.

reply