{"record":{"id":"b302fda27395ce1a","repo":"bazelbuild/bazel","slug":"expected-at-least-one-item","errorCode":null,"errorMessage":"expected at least one item","messagePattern":"expected at least one item","errorType":"exception","errorClass":"EvalException","httpStatus":null,"severity":"error","filePath":"src/main/java/net/starlark/java/eval/MethodLibrary.java","lineNumber":141,"sourceCode":"      if (keyFn.isPresent()) {\n        try {\n          return stream(items)\n              .map(value -> ValueWithComparisonKey.make(value, keyFn.get(), thread))\n              .max(comparing(ValueWithComparisonKey::getComparisonKey, maxOrdering))\n              .get()\n              .getValue();\n        } catch (ValueWithComparisonKey.KeyCallException ex) {\n          Throwables.throwIfInstanceOf(ex.getCause(), EvalException.class);\n          Throwables.throwIfInstanceOf(ex.getCause(), InterruptedException.class);\n          throw new AssertionError(\"Got invalid ValueWithComparisonKey.KeyCallException\", ex);\n        }\n      } else {\n        return maxOrdering.max(items);\n      }\n    } catch (ClassCastException ex) {\n      throw new EvalException(ex.getMessage()); // e.g. unsupported comparison: int <=> string\n    } catch (NoSuchElementException ex) {\n      throw new EvalException(\"expected at least one item\", ex);\n    } finally {\n      EvalUtils.removeIterator(items);\n    }\n  }\n\n  /**\n   * Original value decorated with its comparison key; storing the comparison key alongside the\n   * value ensures that we call the comparison key computation function only once per original value\n   * (which is important in case the function has side effects).\n   */\n  private static final class ValueWithComparisonKey {\n    private final Object value;\n    private final Object comparisonKey;\n\n    private ValueWithComparisonKey(Object value, Object comparisonKey) {\n      this.value = value;\n      this.comparisonKey = comparisonKey;\n    }","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/bazelbuild/bazel/blob/e6e199d0601a244511b4cf18c8b2828aa73db1fd/src/main/java/net/starlark/java/eval/MethodLibrary.java#L123-L159","documentation":"Thrown by the built-in min()/max() when the iterable is empty. Guava's Ordering.max(Iterable) raises NoSuchElementException on an empty input; MethodLibrary converts it to EvalException with the message 'expected at least one item'. Starlark's min/max have no default= parameter, unlike Python's.","triggerScenarios":"max([]), min(()) , max(dict()), or min/max over a comprehension/list that is empty at runtime (e.g. max([f for f in files if f.endswith('.cc')]) when no file matches).","commonSituations":"Glob or filter results that legitimately come back empty (no matching targets, no test files); optional attributes that default to an empty list; first iteration over generated input where the first batch is empty.","solutions":["Guard the call: if len(items) > 0: m = max(items) else: <fallback>.","Seed the iterable with a neutral element when the semantics allow it: max([0] + scores).","Use a defaulting idiom: m = max(items) if items else None (then handle None downstream)."],"exampleFix":"# before\nm = max([f for f in files if f.endswith('.cc')])\n\n# after\ncc = [f for f in files if f.endswith('.cc')]\nm = max(cc) if cc else None","handlingStrategy":"validation","validationCode":"if len(items) == 0:\n    fail(\"cannot take max of empty list\")\nm = max(items)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check emptiness before every min()/max() on filtered data.","Remember Starlark min/max have no default= parameter.","Use `max(items) if items else None` as the standard idiom."],"tags":["starlark","min-max","empty-collection","validation"],"backgroundTag":null,"analyzedSha":"e6e199d0601a244511b4cf18c8b2828aa73db1fd","analyzedAt":"2026-08-14T10:24:27.848Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}