{"record":{"id":"796c55a2da398b33","repo":"SonarSource/sonarqube","slug":"read-timeout-must-be-positive-got","errorCode":null,"errorMessage":"Read timeout must be positive. Got ","messagePattern":"Read timeout must be positive\\. Got ","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sonar-ws/src/main/java/org/sonarqube/ws/client/OkHttpClientBuilder.java","lineNumber":172,"sourceCode":"    this.connectTimeoutMs = l;\n    return this;\n  }\n\n  /**\n   * Set credentials that will be passed on every request\n   */\n  public OkHttpClientBuilder setCredentials(String credentials) {\n    this.credentials = credentials;\n    return this;\n  }\n\n  /**\n   * Sets the default read timeout for new connections. A value of 0 means no timeout.\n   * Default is defined by OkHttp (10 seconds in OkHttp 3.3).\n   */\n  public OkHttpClientBuilder setReadTimeoutMs(long l) {\n    if (l < 0) {\n      throw new IllegalArgumentException(\"Read timeout must be positive. Got \" + l);\n    }\n    this.readTimeoutMs = l;\n    return this;\n  }\n\n  /**\n   * Sets the default response timeout for new connections. A value of 0 means no timeout.\n   * Default is to have no timeout.\n   */\n  public OkHttpClientBuilder setResponseTimeoutMs(long l) {\n    if (l < 0) {\n      throw new IllegalArgumentException(\"Response timeout must be positive. Got \" + l);\n    }\n    this.responseTimeoutMs = l;\n    return this;\n  }\n\n  /**","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/sonar-ws/src/main/java/org/sonarqube/ws/client/OkHttpClientBuilder.java#L154-L190","documentation":"OkHttpClientBuilder.setReadTimeoutMs(long) throws IllegalArgumentException when given a negative value. Zero means no read timeout; the OkHttp default otherwise applies. Like the connect-timeout setter, it validates eagerly so a misconfigured builder fails immediately rather than at request time.","triggerScenarios":"Calling setReadTimeoutMs with a negative long, e.g. from a parsed configuration value or computed duration that went negative; called via provide() or HttpConnector setup.","commonSituations":"Negative values in sonar.properties or client config; duration arithmetic underflow; users setting '-1' expecting 'infinite' instead of the API's 0-for-none convention.","solutions":["Pass 0 to disable the read timeout (not -1)","Clamp with Math.max(0, readTimeoutMs) before calling","Fix the configuration source supplying the negative number"],"exampleFix":"// before\nbuilder.setReadTimeoutMs(-1); // intended 'no timeout'\n// after\nbuilder.setReadTimeoutMs(0); // 0 = no timeout","handlingStrategy":"validation","validationCode":"if (readTimeoutMs < 0) throw new IllegalArgumentException(\"readTimeoutMs must be >= 0, got \" + readTimeoutMs);\nbuilder.setReadTimeoutMs(Math.max(0, readTimeoutMs));","typeGuard":null,"tryCatchPattern":"try {\n  builder.setReadTimeoutMs(cfg.readTimeoutMs());\n} catch (IllegalArgumentException e) {\n  log.warn(\"Bad read timeout, using default\", e);\n}","preventionTips":["Use 0 (not -1) for 'no read timeout'","Validate config-derived longs before passing to the builder","Guard deadline arithmetic so durations cannot go negative"],"tags":["configuration","timeout","okhttp","builder"],"backgroundTag":"invalid-config-value","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}