Skip to content

Commit 44f18b9

Browse files
Patch76claude
andcommitted
fix(addon): bound the job-collision give-up message too
Moving the bound to _raise_supervisor_api_failure left one reporting path uncovered: when a job-group collision exhausts the retry budget, _supervisor_api_call raises its own error from the raw error_text it computed for the marker test, so an oversized collision message was still reported in full. That path was bounded before the move, on the direct REST transport, so this closes a gap the move opened. Bind the size after the marker classification is settled, and cover the give-up path with a regression test. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 177dc2a commit 44f18b9

2 files changed

Lines changed: 32 additions & 0 deletions

File tree

src/ha_mcp/tools/tools_addons.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,10 @@ async def _supervisor_api_call(
726726
if _JOB_COLLISION_MARKER not in error_text.lower():
727727
_raise_supervisor_api_failure(result, endpoint)
728728

729+
# The marker test runs on the raw text; everything below reports
730+
# it, so bind the size once the classification is settled.
731+
error_text = _bounded_supervisor_text(error_text)
732+
729733
remaining = deadline - time.monotonic()
730734
if remaining <= 0:
731735
# The retry budget is exhausted; the group may be stuck or

tests/src/unit/test_tools_addons.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4623,6 +4623,34 @@ async def test_addon_mode_invalid_json_error_caps_response_body(self, monkeypatc
46234623
"x" * (50 * 1024 - len(suffix)) + suffix
46244624
)
46254625

4626+
@pytest.mark.asyncio
4627+
async def test_job_collision_giveup_message_is_capped(self, monkeypatch):
4628+
"""An exhausted job-collision retry cannot report an unbounded error."""
4629+
from ha_mcp.tools import tools_addons
4630+
from ha_mcp.tools.tools_addons import _supervisor_api_call
4631+
4632+
monkeypatch.delenv("SUPERVISOR_TOKEN", raising=False)
4633+
monkeypatch.setattr(tools_addons, "_JOB_COLLISION_RETRY_WINDOW", 0.0)
4634+
client = _make_mock_client()
4635+
client.send_websocket_message = AsyncMock(
4636+
return_value={
4637+
"success": False,
4638+
"error": (
4639+
"Command failed: another job is running for job group "
4640+
+ "v" * (50 * 1024 + 1)
4641+
),
4642+
}
4643+
)
4644+
4645+
with pytest.raises(ToolError) as exc_info:
4646+
await _supervisor_api_call(client, "/addons/x/restart", method="POST")
4647+
4648+
payload = _parse_tool_error(exc_info)
4649+
suffix = "\n[Supervisor response truncated to 50 KiB]"
4650+
message = payload["error"]["message"]
4651+
assert message.endswith(suffix)
4652+
assert len(message) == 50 * 1024
4653+
46264654
@pytest.mark.asyncio
46274655
async def test_core_routed_failure_message_is_capped(self, monkeypatch):
46284656
"""A Core-relayed Supervisor failure cannot produce an unbounded error."""

0 commit comments

Comments
 (0)