Skip to content

Introduce ErrorRecord dataclass for structured error files - #81

Open
yoonspark wants to merge 5 commits into
mainfrom
refactor/error-record-dataclass
Open

Introduce ErrorRecord dataclass for structured error files#81
yoonspark wants to merge 5 commits into
mainfrom
refactor/error-record-dataclass

Conversation

@yoonspark

@yoonspark yoonspark commented Apr 13, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Replace write_error_file helper with ErrorRecord dataclass that owns read, write, and capture-from-exception logic
  • Write error details into .setup-failed sentinel files so setup failures are inspectable beyond just the sentinel's existence

Testing

  • Unit tests (247 passed)
  • Integration tests (including Slurm ones)
  • Manual test of a local-task pipeline
    • Confirm report dashboard displays errors correctly
    • Confirm .err files contain details in correct format
  • Manual test of a Slurm task with setup failure
    • Confirm the sentinel file contains error details in correct format

- Replace `write_error_file` helper with `ErrorRecord` dataclass that
  owns read, write, and capture-from-exception logic
- Drop the `file` key from the on-disk `.err` schema; the stem is
  already recoverable from the filename
- Write error details into `.setup-failed` sentinel files so setup
  failures are inspectable beyond just the sentinel's existence
The `.err` stem is derived from the output filename, which does not
always recover the original input filename. Store it on the record
so `PipelineOutput` can display the input the user recognizes
@yoonspark
yoonspark force-pushed the refactor/error-record-dataclass branch from b53a311 to ee08cc9 Compare April 13, 2026 20:42
@yoonspark yoonspark linked an issue Apr 22, 2026 that may be closed by this pull request
@yoonspark
yoonspark requested a review from cswaney April 22, 2026 15:03

@cswaney cswaney left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the idea of incorporating the error writing function into a class. This is a clean design.

Might question is whether ErrorRecord and FileError need to be separate classes?

Their fields largely overlap—the differences are path (could be optional), the str vs datetime timestamp, and Pydantic vs dataclass.

Would it work to collapse them into one type with file: str | None, path: str | None, timestamp: datetime? That would let PipelineReport.errors hold the records directly and remove the conversion logic in models.py:625-639.

I think there is also a question of whether path should be set on read/write.

Open to thoughts.

Comment thread tests/unit/test_utils.py
with pytest.raises(ValueError, match="invalid error record"):
ErrorRecord.read(path)

def test_read_without_file_key(self, tmp_path: Path):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicates test_write_read_roundtrip_without_file?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests look similar but cover different cases.

  • test_write_read_roundtrip_without_file writes the file using ErrorRecord.write(), hence testing ErrorRecord's full write-read round trip.
  • test_read_without_file_key writes the file using raw Path.write_text(), hence testing ErrorRecord's read behavior only.

`FileError` duplicated every `ErrorRecord` field, so reading an .err
file meant unpacking the record and rebuilding it field by field. It is
now a slotted dataclass holding the record plus `path`, the file's
location. Timestamps stay raw strings instead of being parsed, so a
malformed one no longer discards the whole record.
@yoonspark

Copy link
Copy Markdown
Collaborator Author

@cswaney Revisiting this PR to integrate your feedback. I updated FileError to be a data class that stores pointer to ErrorRecord. This way, we minimize unnecessary data copy. Furthermore, data class is much more lightweight than Pydantic model. I am still retaining FileError to store path (to the actual error file), which does not nicely fit into ErrorRecord both technically and conceptually. Let me know if you have a different thought.

On a separate but related note, we should also replace other Pydantic models used by PipelineOutput (e.g., TaskProgress, TaskMeta, PipelineReport) with data classes because they all serve as simple data stores for internal use. This can be tackled as a part of larger refactor around PipelineOutput (see #124).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Standardize reading/writing of error files

2 participants