Skip to content

Exception serialization improvement #309

Open

Description

@kigawas

When job failed, the result becomes an exception, which causes problems on serialization without pickle.

async def job_failed(exc: BaseException) -> None:
    self.jobs_failed += 1
    result_data_ = serialize_result(
        function=function_name,
        args=args,
        kwargs=kwargs,
        job_try=job_try,
        enqueue_time_ms=enqueue_time_ms,
        success=False,
        result=exc,
        start_ms=start_ms,
        finished_ms=timestamp_ms(),
        ref=f'{job_id}:{function_name}',
        serializer=self.job_serializer,
        queue_name=self.queue_name,
    )
    await asyncio.shield(self.finish_failed_job(job_id, result_data_))

Activity

  1. iamlikeme commented on Nov 19, 2022

    @iamlikeme
    Contributor

    Since pickle is the standard serializer, you are apparently using a custom serializer. So it is up to you how to serialize exceptions.
    Perhaps I misunderstand your question?

  2. kigawas commented on Nov 24, 2022

    @kigawas
    ContributorAuthor

    Since pickle is the standard serializer, you are apparently using a custom serializer. So it is up to you how to serialize exceptions. Perhaps I misunderstand your question?

    How can I serialize exceptions to JSON when the job failed?

  3. iamlikeme commented on Dec 11, 2022

    @iamlikeme
    Contributor

    How to serialize an exception to JSON is a very generic question outside the scope of arq. StackOverflow has some suggestion.

  4. heshiming commented on Aug 9, 2023

    @heshiming

    I think what the OP meant to ask was how to serialize the exception when job.result() is supposed to reraise it but can't due to serialization.

    I'm on version 0.25.0. When job.result() is called on a job using the msgpack deserializer, it immediately fails with arq.jobs.SerializationError: unable to serialize result. From the code, deserialization happens before reraising. And since msgpack cannot serialize an exception, info.result will not be an Exception.

    As a serializer, msgpack cannot deal with the case where the job failed due to an exception.

  5. SimonDahrs commented on Feb 5, 2025

    @SimonDahrs

    Found a workaround when using msgpack: you can define your custom serialization function that checks if the 'r' field (result) in the dict passed to it is of type Exception. If it is, you can override that field with the str repr of the exception so that msgpack can serialize it. This is how I do it:

    def job_msgpack_serialize(obj: dict[str, Any]) -> bytes:
        if "r" in obj and isinstance(obj["r"], Exception):
            obj["r"] = repr(obj["r"])  # make sure exceptions are serializable by msgpack
        return msgpack.packb(obj)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions