{"record":{"id":"6e4747a1e1d255b6","repo":"apache/hadoop","slug":"pairs-must-be-neither-null-nor-empty","errorCode":null,"errorMessage":"pairs must be neither null nor empty.","messagePattern":"pairs must be neither null nor empty\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/io/retry/RetryPolicies.java","lineNumber":416,"sourceCode":"          throw new IllegalArgumentException(\"sleepMillis = \" + sleepMillis + \" < 0\");\n        }\n\n        this.numRetries = numRetries;\n        this.sleepMillis = sleepMillis;\n      }\n      \n      @Override\n      public String toString() {\n        return numRetries + \"x\" + sleepMillis + \"ms\";\n      }\n    }\n\n    private final List<Pair> pairs;\n    private String myString;\n\n    public MultipleLinearRandomRetry(List<Pair> pairs) {\n      if (pairs == null || pairs.isEmpty()) {\n        throw new IllegalArgumentException(\"pairs must be neither null nor empty.\");\n      }\n      this.pairs = Collections.unmodifiableList(pairs);\n    }\n\n    @Override\n    public RetryAction shouldRetry(Exception e, int curRetry, int failovers,\n        boolean isIdempotentOrAtMostOnce) throws Exception {\n      final Pair p = searchPair(curRetry);\n      if (p == null) {\n        //no more retries.\n        return new RetryAction(RetryAction.RetryDecision.FAIL, 0 , \"Retry \" +\n            \"all pairs in MultipleLinearRandomRetry: \" + pairs);\n      }\n\n      //calculate sleep time and return.\n      // ensure 0.5 <= ratio <=1.5\n      final double ratio = ThreadLocalRandom.current().nextDouble() + 0.5;\n      final long sleepTime = Math.round(p.sleepMillis * ratio);","sourceCodeStart":398,"sourceCodeEnd":434,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/io/retry/RetryPolicies.java#L398-L434","documentation":"MultipleLinearRandomRetry needs at least one (numRetries, sleepMillis) pair; constructing it with null or an empty list throws immediately. An empty schedule has no retry behavior, and Hadoop treats that as a configuration error rather than 'never retry' — dedicated policies exist for that intent.","triggerScenarios":"Parsing a retry spec that is empty or whose tokens all fail to parse, leaving an empty list; programmatic list construction inside a loop that never executes; refactors leaving a stub list behind.","commonSituations":"dfs.client.retry.policy.spec set to '' or to a value the parser cannot tokenize; conditional code paths that append pairs only when features are enabled, producing zero pairs.","solutions":["If the intent is 'no retries', use RetryPolicies.TRY_ONCE_THEN_FAIL (or noRetry) instead of an empty MultipleLinearRandomRetry.","Default the spec when blank — e.g. fall back to the standard '10000,6,60000,10' rather than constructing from nothing.","Validate pairs != null && !pairs.isEmpty() before construction and include the raw spec string in the error."],"exampleFix":"// before\nRetryPolicy p = new MultipleLinearRandomRetry(Collections.emptyList());\n\n// after\nRetryPolicy p = pairs == null || pairs.isEmpty()\n    ? RetryPolicies.TRY_ONCE_THEN_FAIL\n    : new MultipleLinearRandomRetry(pairs);","handlingStrategy":"validation","validationCode":"if (pairs == null || pairs.isEmpty()) {\n  throw new IllegalArgumentException(\n      \"retry spec produced no pairs: '\" + rawSpec + \"'\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use TRY_ONCE_THEN_FAIL when retries are unwanted instead of an empty schedule.","Default blank retry specs to a sane schedule rather than constructing from nothing.","Check list-producing config for conditionally-empty branches."],"tags":["retry-policy","configuration","illegal-argument","hadoop-common"],"backgroundTag":"invalid-config-value","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}