Skip to content

Commit c571feb

Browse files
statxcanderdc
andauthored
fix(cli): surface skipped validators in miner post/check error path (#990)
Co-authored-by: Ander <61125407+anderdc@users.noreply.github.com>
1 parent 39d34fa commit c571feb

2 files changed

Lines changed: 74 additions & 1 deletion

File tree

gittensor/cli/miner_commands/helpers.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,18 @@ def _require_validator_axons(
135135
metagraph, min_vtrust=min_vtrust, min_stake=min_stake
136136
)
137137
if not validator_axons:
138-
_error('No reachable validator axons found on the network.', json_mode)
138+
if excluded:
139+
msg = (
140+
f'No validators passed --min-vtrust={min_vtrust:g} / '
141+
f'--min-stake={min_stake:,.0f} α; all {len(excluded)} candidate(s) excluded.'
142+
)
143+
if json_mode:
144+
click.echo(json.dumps({'success': False, 'error': msg, 'skipped': excluded}))
145+
else:
146+
_render_skipped_validators(excluded, json_mode)
147+
console.print(f'[red]Error: {msg}[/red]')
148+
else:
149+
_error('No reachable validator axons found on the network.', json_mode)
139150
sys.exit(1)
140151
return validator_axons, validator_uids, excluded
141152

tests/cli/test_miner_commands.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
_pat_check_aggregate_counts,
1717
_pat_post_aggregate_counts,
1818
_pat_post_row_category,
19+
_require_validator_axons,
1920
)
2021

2122

@@ -184,6 +185,67 @@ def test_combines_reasons_when_both_fail(self):
184185
assert len(excluded[0]['reasons']) == 2
185186

186187

188+
class TestRequireValidatorAxonsErrorPath:
189+
"""Regression: the error path must surface the same `excluded` payload the
190+
success path renders, so operators see which threshold eliminated each UID."""
191+
192+
def test_filtered_json_envelope_includes_skipped_array(self, capsys):
193+
mg = _fake_metagraph(
194+
[
195+
(0.99, True, 5_000.0),
196+
(0.85, True, 3_000.0),
197+
(0.72, True, 8_000.0),
198+
]
199+
)
200+
with pytest.raises(SystemExit) as exc_info:
201+
_require_validator_axons(mg, True, min_vtrust=0.25, min_stake=15_000.0)
202+
assert exc_info.value.code == 1
203+
payload = json.loads(capsys.readouterr().out.strip())
204+
assert payload['success'] is False
205+
assert '--min-stake' in payload['error']
206+
assert '--min-vtrust' in payload['error']
207+
assert len(payload['skipped']) == 3
208+
assert {entry['uid'] for entry in payload['skipped']} == {0, 1, 2}
209+
assert all(entry['reasons'] for entry in payload['skipped'])
210+
211+
def test_filtered_tty_renders_skipped_table_and_error(self, capsys):
212+
mg = _fake_metagraph(
213+
[
214+
(0.99, True, 5_000.0),
215+
(0.85, False, 50_000.0),
216+
]
217+
)
218+
with pytest.raises(SystemExit) as exc_info:
219+
_require_validator_axons(mg, False, min_vtrust=0.25, min_stake=15_000.0)
220+
assert exc_info.value.code == 1
221+
out = capsys.readouterr().out
222+
assert 'Skipped Validators' in out
223+
assert 'No validators passed' in out
224+
assert 'Error:' in out
225+
226+
def test_truly_empty_metagraph_keeps_generic_message(self, capsys):
227+
mg = _fake_metagraph([])
228+
with pytest.raises(SystemExit) as exc_info:
229+
_require_validator_axons(mg, True, min_vtrust=0.25, min_stake=15_000.0)
230+
assert exc_info.value.code == 1
231+
payload = json.loads(capsys.readouterr().out.strip())
232+
assert payload == {
233+
'success': False,
234+
'error': 'No reachable validator axons found on the network.',
235+
}
236+
237+
def test_subvtrust_only_metagraph_keeps_generic_message(self, capsys):
238+
# Sub-vtrust UIDs are dropped silently and never enter `excluded`,
239+
# so the message should remain the generic one — not the threshold one.
240+
mg = _fake_metagraph([(0.10, True, 50_000.0), (0.05, True, 100_000.0)])
241+
with pytest.raises(SystemExit) as exc_info:
242+
_require_validator_axons(mg, True, min_vtrust=0.25, min_stake=15_000.0)
243+
assert exc_info.value.code == 1
244+
payload = json.loads(capsys.readouterr().out.strip())
245+
assert payload['error'] == 'No reachable validator axons found on the network.'
246+
assert 'skipped' not in payload
247+
248+
187249
class TestPatCheckAggregateCounts:
188250
def test_splits_valid_no_pat_invalid_and_no_response(self):
189251
results = [

0 commit comments

Comments
 (0)