#7693·flower

weighted_loss_avg() raises ZeroDivisionError when every result reports zero evaluation examples

Author: Atishyy27Created Jul 27, 2026Updated Jul 27, 2026

Describe the bug

weighted_loss_avg() in framework/py/flwr/server/strategy/aggregate.py divides by the total number of evaluation examples without guarding against zero:

python
num_total_evaluation_examples = sum(num_examples for (num_examples, _) in results)
weighted_losses = [num_examples * loss for num_examples, loss in results]
return sum(weighted_losses) / num_total_evaluation_examples

If every client in a round reports num_examples=0 (a degenerate or empty local evaluation partition), this raises ZeroDivisionError: float division by zero and aborts the round.

The callers — FedAvg.aggregate_evaluate, FaultTolerantFedAvg.aggregate_evaluate, FedAvgAndroid.aggregate_evaluate — only guard if not results: return None, {}. That catches an empty result list, but not a non-empty list whose examples all sum to zero.

This is the same class as #7645 (aggregate() returning NaN weights on a zero total), just in the evaluation path — and here it hard-raises rather than silently producing NaN.

Steps to reproduce

python
from flwr.server.strategy.aggregate import weighted_loss_avg

weighted_loss_avg([(0, 2.0), (0, 3.0)])
# ZeroDivisionError: float division by zero

Expected behavior

A clear ValueError explaining that the total number of evaluation examples must be greater than zero, consistent with the guard proposed for aggregate() in #7646.

I have a fix and a regression test ready and will open a PR referencing this issue.