Skip to content

exceptions

JobExecutionError

Bases: RuntimeError

Forwards errors in the execution of a task that are due to external factors

This error wraps and forwards errors occurred during the execution of tasks, but related to external factors like:

  1. A negative exit code (e.g. because the task received a TERM or KILL signal);
  2. An error on the executor side (e.g. the SLURM executor could not find the pickled file with task output).

This error also adds information that is useful to track down and debug the failing task within a workflow.

Attributes:

Name Type Description
info Optional[str]

A free field for additional information

cmd_file Optional[str]

Path to the file of the command that was executed (e.g. a SLURM submission script).

stdout_file Optional[str]

Path to the file with the command stdout

stderr_file Optional[str]

Path to the file with the command stderr

Source code in fractal_server/app/runner/exceptions.py
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
class JobExecutionError(RuntimeError):
    """
    Forwards errors in the execution of a task that are due to external factors

    This error wraps and forwards errors occurred during the execution of
    tasks, but related to external factors like:

    1. A negative exit code (e.g. because the task received a TERM or KILL
       signal);
    2. An error on the executor side (e.g. the SLURM executor could not
       find the pickled file with task output).

    This error also adds information that is useful to track down and debug the
    failing task within a workflow.

    Attributes:
        info:
            A free field for additional information
        cmd_file:
            Path to the file of the command that was executed (e.g. a SLURM
            submission script).
        stdout_file:
            Path to the file with the command stdout
        stderr_file:
            Path to the file with the command stderr
    """

    cmd_file: Optional[str] = None
    stdout_file: Optional[str] = None
    stderr_file: Optional[str] = None
    info: Optional[str] = None

    def __init__(
        self,
        *args,
        cmd_file: Optional[str] = None,
        stdout_file: Optional[str] = None,
        stderr_file: Optional[str] = None,
        info: Optional[str] = None,
    ):
        super().__init__(*args)
        self.cmd_file = cmd_file
        self.stdout_file = stdout_file
        self.stderr_file = stderr_file
        self.info = info

    def _read_file(self, filepath: str) -> str:
        """
        Return the content of a text file, and handle the cases where it is
        empty or missing
        """
        if os.path.exists(filepath):
            with open(filepath, "r") as f:
                content = f.read()
                if content:
                    return f"Content of {filepath}:\n{content}"
                else:
                    return f"File {filepath} is empty\n"
        else:
            return f"File {filepath} is missing\n"

    def assemble_error(self) -> str:
        """
        Read the files that are specified in attributes, and combine them in an
        error message.
        """
        if self.cmd_file:
            content = self._read_file(self.cmd_file)
            cmd_content = f"COMMAND:\n{content}\n\n"
        else:
            cmd_content = ""
        if self.stdout_file:
            content = self._read_file(self.stdout_file)
            out_content = f"STDOUT:\n{content}\n\n"
        else:
            out_content = ""
        if self.stderr_file:
            content = self._read_file(self.stderr_file)
            err_content = f"STDERR:\n{content}\n\n"
        else:
            err_content = ""

        content = f"{cmd_content}{out_content}{err_content}"
        if self.info:
            content = f"{content}ADDITIONAL INFO:\n{self.info}\n\n"

        if not content:
            content = str(self)
        message = f"JobExecutionError\n\n{content}"
        return message

_read_file(filepath)

Return the content of a text file, and handle the cases where it is empty or missing

Source code in fractal_server/app/runner/exceptions.py
86
87
88
89
90
91
92
93
94
95
96
97
98
99
def _read_file(self, filepath: str) -> str:
    """
    Return the content of a text file, and handle the cases where it is
    empty or missing
    """
    if os.path.exists(filepath):
        with open(filepath, "r") as f:
            content = f.read()
            if content:
                return f"Content of {filepath}:\n{content}"
            else:
                return f"File {filepath} is empty\n"
    else:
        return f"File {filepath} is missing\n"

assemble_error()

Read the files that are specified in attributes, and combine them in an error message.

Source code in fractal_server/app/runner/exceptions.py
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
def assemble_error(self) -> str:
    """
    Read the files that are specified in attributes, and combine them in an
    error message.
    """
    if self.cmd_file:
        content = self._read_file(self.cmd_file)
        cmd_content = f"COMMAND:\n{content}\n\n"
    else:
        cmd_content = ""
    if self.stdout_file:
        content = self._read_file(self.stdout_file)
        out_content = f"STDOUT:\n{content}\n\n"
    else:
        out_content = ""
    if self.stderr_file:
        content = self._read_file(self.stderr_file)
        err_content = f"STDERR:\n{content}\n\n"
    else:
        err_content = ""

    content = f"{cmd_content}{out_content}{err_content}"
    if self.info:
        content = f"{content}ADDITIONAL INFO:\n{self.info}\n\n"

    if not content:
        content = str(self)
    message = f"JobExecutionError\n\n{content}"
    return message

TaskExecutionError

Bases: RuntimeError

Forwards errors occurred during the execution of a task

This error wraps and forwards errors occurred during the execution of tasks, when the exit code is larger than 0 (i.e. the error took place within the task). This error also adds information that is useful to track down and debug the failing task within a workflow.

Attributes:

Name Type Description
workflow_task_id Optional[int]

ID of the workflow task that failed.

workflow_task_order Optional[int]

Order of the task within the workflow.

task_name Optional[str]

Human readable name of the failing task.

Source code in fractal_server/app/runner/exceptions.py
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class TaskExecutionError(RuntimeError):
    """
    Forwards errors occurred during the execution of a task

    This error wraps and forwards errors occurred during the execution of
    tasks, when the exit code is larger than 0 (i.e. the error took place
    within the task). This error also adds information that is useful to track
    down and debug the failing task within a workflow.

    Attributes:
        workflow_task_id:
            ID of the workflow task that failed.
        workflow_task_order:
            Order of the task within the workflow.
        task_name:
            Human readable name of the failing task.
    """

    workflow_task_id: Optional[int] = None
    workflow_task_order: Optional[int] = None
    task_name: Optional[str] = None

    def __init__(
        self,
        *args,
        workflow_task_id: Optional[int] = None,
        workflow_task_order: Optional[int] = None,
        task_name: Optional[str] = None,
    ):
        super().__init__(*args)
        self.workflow_task_id = workflow_task_id
        self.workflow_task_order = workflow_task_order
        self.task_name = task_name