@@ -7453,6 +7453,71 @@ def test_list_skips_bad_file_with_valid_sibling(self, project_dir):
74537453 assert len(runs) == 1
74547454 assert runs[0]["workflow_id"] == "good-run"
74557455
7456+ def test_list_skips_invalid_utf8_with_valid_sibling(self, project_dir):
7457+ from specify_cli.workflows.engine import WorkflowEngine, WorkflowDefinition
7458+
7459+ runs_dir = project_dir / ".specify" / "workflows" / "runs"
7460+ bad_dir = runs_dir / "bad-utf8"
7461+ bad_dir.mkdir(parents=True)
7462+ (bad_dir / "state.json").write_bytes(b"\xff\xfe invalid utf8")
7463+
7464+ yaml_str = """
7465+ schema_version: "1.0"
7466+ workflow:
7467+ id: "good-run-utf8"
7468+ name: "Good Run UTF8"
7469+ version: "1.0.0"
7470+ steps:
7471+ - id: step-one
7472+ type: shell
7473+ run: "echo test"
7474+ """
7475+ definition = WorkflowDefinition.from_string(yaml_str)
7476+ engine = WorkflowEngine(project_dir)
7477+ engine.execute(definition)
7478+
7479+ runs = engine.list_runs()
7480+ assert len(runs) == 1
7481+ assert runs[0]["workflow_id"] == "good-run-utf8"
7482+
7483+ def test_list_skips_oserror_with_valid_sibling(self, project_dir, monkeypatch):
7484+ import builtins
7485+ from specify_cli.workflows.engine import WorkflowEngine, WorkflowDefinition
7486+
7487+ runs_dir = project_dir / ".specify" / "workflows" / "runs"
7488+ bad_dir = runs_dir / "bad-oserror"
7489+ bad_dir.mkdir(parents=True)
7490+ state_file = bad_dir / "state.json"
7491+ state_file.write_text('{"run_id": "bad"}', encoding="utf-8")
7492+
7493+ original_open = builtins.open
7494+
7495+ def _mock_open(path, *args, **kwargs):
7496+ if str(path).endswith("state.json") and "bad-oserror" in str(path):
7497+ raise OSError("permission denied")
7498+ return original_open(path, *args, **kwargs)
7499+
7500+ monkeypatch.setattr(builtins, "open", _mock_open)
7501+
7502+ yaml_str = """
7503+ schema_version: "1.0"
7504+ workflow:
7505+ id: "good-run-oserror"
7506+ name: "Good Run OSError"
7507+ version: "1.0.0"
7508+ steps:
7509+ - id: step-one
7510+ type: shell
7511+ run: "echo test"
7512+ """
7513+ definition = WorkflowDefinition.from_string(yaml_str)
7514+ engine = WorkflowEngine(project_dir)
7515+ engine.execute(definition)
7516+
7517+ runs = engine.list_runs()
7518+ assert len(runs) == 1
7519+ assert runs[0]["workflow_id"] == "good-run-oserror"
7520+
74567521
74577522# ===== Workflow Registry Tests =====
74587523
0 commit comments