Skip to content

Bug: scores.csv error handling can crash on undecodable file content #1457

Description

@yifanxiong272

Summary

Several data-science evaluators catch errors while parsing scores.csv, but then read the same file with Path.read_text() while constructing the diagnostic message.

If scores.csv exists but contains bytes that are not valid UTF-8, the initial pandas.read_csv(...) failure is caught, but the exception handler raises a second uncaught UnicodeDecodeError:

score_fp.read_text()

As a result, the evaluator crashes instead of returning structured negative feedback.

To Reproduce

  1. Check out RD-Agent main at commit 6762f84f9bc0f5c6486c50a00e128a57ac6c3683.

  2. Install RD-Agent from source.

  3. Create test/scenarios/data_science/test_scores_csv_decode_error.py:

from pathlib import Path
from types import SimpleNamespace

import rdagent.components.coder.data_science.workflow.eval as workflow_eval
from rdagent.components.coder.CoSTEER.evaluators import CoSTEERSingleFeedback
from rdagent.components.coder.data_science.workflow.eval import (
    WorkflowGeneralCaseSpecEvaluator,
)


class FakeTask:
    def get_task_information(self):
        return "demo task"


class FakeImplementation:
    def __init__(self, workspace_path):
        self.workspace_path = Path(workspace_path)
        self.file_dict = {
            "main.py": "pass",
            "spec/workflow.md": "spec",
        }

    def execute(self, env=None, entry=None):
        return "inference finished"

    def inject_files(self, **files):
        self.file_dict.update(files)

    def run(self, env=None, entry=None):
        return SimpleNamespace(stdout="submission check passed", exit_code=0)


def test_workflow_evaluator_handles_undecodable_scores_csv(tmp_path, monkeypatch):
    monkeypatch.setattr(
        workflow_eval,
        "get_ds_env",
        lambda *args, **kwargs: SimpleNamespace(
            conf=SimpleNamespace(running_timeout_period=1),
        ),
    )
    monkeypatch.setattr(
        workflow_eval,
        "get_clear_ws_cmd",
        lambda *args, **kwargs: "true",
    )
    monkeypatch.setattr(
        workflow_eval,
        "build_cls_from_json_with_retry",
        lambda *args, **kwargs: CoSTEERSingleFeedback(
            execution="ok",
            return_checking="ok",
            code="ok",
            final_decision=True,
        ),
    )

    (tmp_path / "scores.csv").write_bytes(b"\xff\xff\xff\n")

    scen = SimpleNamespace(
        debug_path="/tmp/demo-input",
        real_debug_timeout=lambda: 1,
        get_scenario_all_desc=lambda eda_output=None: "scenario",
    )
    evaluator = WorkflowGeneralCaseSpecEvaluator(scen=scen)

    feedback = evaluator.evaluate(
        FakeTask(),
        FakeImplementation(tmp_path),
        None,
    )

    assert feedback.final_decision is False
    assert "scores.csv" in feedback.return_checking
  1. Run:
python -m pytest test/scenarios/data_science/test_scores_csv_decode_error.py -q
  1. Observe that the test fails with an uncaught UnicodeDecodeError.

Expected Behavior

An undecodable or malformed scores.csv should be treated as invalid generated output.

The evaluator should return structured negative feedback, for example:

feedback.final_decision is False

and include a diagnostic mentioning the scores.csv parse/decode problem.

Actual Behavior

The evaluator raises an uncaught exception:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte

So no feedback object is returned.

Screenshot

Not applicable; this is a deterministic unit-level reproduction.

Environment

  • Name of current operating system: macOS
  • Processor architecture: arm64
  • Python version: 3.11.15
  • RD-Agent version: 0.8.0, main@6762f84f9bc0f5c6486c50a00e128a57ac6c3683
  • Container: not used in this reproduction

Additional Notes

The workflow evaluator contains this exception handler:

except Exception as e:
    score_check_text += f"\n[Error] in checking the scores.csv file: {e}\nscores.csv's content:\n-----\n{score_fp.read_text()}\n-----"
    score_ret_code = 1

The same pattern also appears in:

  • rdagent/components/coder/data_science/pipeline/eval.py
  • rdagent/scenarios/data_science/dev/runner/eval.py

The handler catches the first parsing error, but score_fp.read_text() can fail for the same artifact before the evaluator can set score_ret_code and return feedback.

A possible fix is to make diagnostic file reading best-effort, for example by using errors="replace" or catching decode errors separately before appending the raw file content to the feedback.

Activity

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

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions