Skip to content

Commit

Permalink
Add isDefined to ErrorOccurrence and update docs.
Browse files Browse the repository at this point in the history
  • Loading branch information
SyntaxColoring committed May 30, 2024
1 parent 7de5e83 commit bb064e9
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 31 deletions.
5 changes: 3 additions & 2 deletions api/src/opentrons/protocol_engine/commands/pick_up_tip.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,10 @@ class TipPhysicallyMissingError(ErrorOccurrence):
of the pipette.
"""

isDefined = True
errorType: Literal["tipPhysicallyMissing"] = "tipPhysicallyMissing"
errorCode: str = ErrorCodes.TIP_PICKUP_FAILED.value.code
detail: str = "No tip detected."
errorCode = ErrorCodes.TIP_PICKUP_FAILED.value.code
detail = "No tip detected."


@dataclass
Expand Down
104 changes: 75 additions & 29 deletions api/src/opentrons/protocol_engine/errors/error_occurrence.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from logging import getLogger

from datetime import datetime
from textwrap import dedent
from typing import Any, Dict, List, Type, Union, Optional, Sequence
from pydantic import BaseModel, Field
from opentrons_shared_data.errors.codes import ErrorCodes
Expand Down Expand Up @@ -43,50 +44,95 @@ def from_failed(
id: str = Field(..., description="Unique identifier of this error occurrence.")
createdAt: datetime = Field(..., description="When the error occurred.")

errorCode: str = Field(
default=ErrorCodes.GENERAL_ERROR.value.code,
description=(
"An enumerated error code for the error type."
" This is intended to be shown to the robot operator to direct them to the"
" correct rough area for troubleshooting."
isDefined: bool = Field(
default=False, # default=False for database backwards compatibility.
description=dedent(
"""\
Whether this error is *defined.*
*Defined* errors have a strictly defined cause and effect, and we generally
design them to be recoverable. For example, a `pickUpTip` command might
return a `tipPhysicallyMissing` error, which is defined, and which you can
recover from by doing a new `pickUpTip` in a different location.
The `errorType` and `errorInfo` fields are useful for reacting to defined
errors.
*Undefined* errors are everything else. They could represent more obscure
hardware failures that we aren't handling yet, or just bugs in our software.
You can continue issuing commands to a run after it encounters an undefined
error, but the robot may not behave well. For example, if a movement command
fails with an undefined error, it could leave the robot in a messed-up
state, and the next movement command could have bad path planning that
collides the pipettes with stuff on the deck. We allow you to take this risk
because it's sometimes better than safely stopping the run, which can
waste time and reagents.
"""
),
)

# TODO(mm, 2023-09-07):
# The Opentrons App and Flex ODD use `errorType` in the title of error modals, but it's unclear
# if they should. Is this field redundant now that we have `errorCode` and `detail`?
#
# In practice, this is often the source code name of our Python exception type.
# Should we derive this from `errorCode` instead? Like how HTTP code 404 is always "not found."
errorType: str = Field(
...,
description=(
"A short name for the error type that occurred, like `PipetteOverpressure`."
" This can be a bit more specific than `errorCode`."
description=dedent(
"""\
This field has two meanings.
When `isDefined` is `true`, this is a machine- and developer-readable
identifier for what kind of error this is. You can use this to implement
interactive error recovery flows, like watching for `"overpressure"` errors
so you can tell the operator to unclog the tip.
When `isDefined` is `false`, this is deprecated. For historical reasons,
it will be the Python class name of some internal exception,
like `"KeyError"` or `"UnexpectedProtocolError"`. The string values are not
stable across software versions. If you're looking for something to show to
robot operators, use `errorCode` and `detail` instead.
"""
),
)

errorCode: str = Field(
default=ErrorCodes.GENERAL_ERROR.value.code,
description=dedent(
"""\
An enumerated error code for the error type.
This is intended to be shown to the robot operator to direct them to the
correct rough area for troubleshooting.
"""
),
)

detail: str = Field(
...,
description=(
"A short human-readable message about the error."
"\n\n"
"This is intended to provide the robot operator with more specific details than"
" `errorCode` alone. It should be no longer than a couple of sentences,"
" and it should not contain internal newlines or indentation."
"\n\n"
" It should not internally repeat `errorCode`, but it may internally repeat `errorType`"
" if it helps the message make sense when it's displayed in its own separate block."
description=dedent(
"""\
A short human-readable message about the error.
This is intended to provide the robot operator with more specific details than
`errorCode` alone. It should be no longer than a couple of sentences,
and it should not contain internal newlines or indentation.
It should not internally repeat `errorCode`, but it may internally repeat `errorType`
if it helps the message make sense when it's displayed in its own separate block.
"""
),
)

errorInfo: Dict[str, str] = Field(
default={},
description=(
"Specific details about the error that may be useful for determining cause."
" This might contain the same information as `detail`, but in a more structured form."
" It might also contain additional information that was too verbose or technical"
" to put in `detail`."
description=dedent(
"""\
Specific structured details about the error that may be useful for
determining what happened.
This might contain the same information as `detail` in a more structured form.
It might also contain additional information that was too verbose or technical
to put in `detail`.
If `isDefined` is `true`, this object may have guaranteed contents, depending
on `errorType`. If `isDefined` is `false`, you should not rely on any
particular contents.
"""
),
)

Expand Down

0 comments on commit bb064e9

Please sign in to comment.