{"record":{"id":"75cbbaae4f39d2d4","repo":"gradle/gradle","slug":"more-progress-was-logged-than-there-should-be","errorCode":null,"errorMessage":"More progress was logged than there should be ({} > {})","messagePattern":"More progress was logged than there should be \\((.+?) > (.+?)\\)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"platforms/core-runtime/logging/src/main/java/org/gradle/internal/logging/console/ProgressBar.java","lineNumber":156,"sourceCode":"            0,\n            totalProgress);\n    }\n\n    public void moreProgress(int totalProgress) {\n        total += totalProgress;\n        formatted = null;\n    }\n\n    public void update(boolean failing) {\n        this.current++;\n        if (current > total) {\n            if (deadlockPreventer == null) {\n                deadlockPreventer = Executors.newSingleThreadExecutor();\n            }\n            Future<?> ignored = deadlockPreventer.submit(() -> {\n                // do not do this directly or a deadlock happens\n                // to prevent that deadlock, execute it separately in another thread\n                LOGGER.warn(\"More progress was logged than there should be ({} > {})\", current, total);\n            });\n        }\n        this.failing = this.failing || failing;\n        formatted = null;\n    }\n\n    public List<Span> formatProgress(boolean timerEnabled, long elapsedTime) {\n        String elapsedTimeStr = elapsedTimeFormatter.format(elapsedTime);\n        if (formatted != null && elapsedTimeStr.equals(lastElapsedTimeStr)) {\n            return formatted;\n        }\n\n        int consoleCols = consoleMetaData.getCols();\n\n        // Calculate progress percentage for both display and taskbar\n        int progressPercent = (int) (current * 100.0 / total);\n\n        // Prepend taskbar progress sequence (invisible control sequence)","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/gradle/gradle/blob/534f27719b66953f95cc907aae7f2c1b12f5482d/platforms/core-runtime/logging/src/main/java/org/gradle/internal/logging/console/ProgressBar.java#L138-L174","documentation":"ProgressBar tracks an operation's progress against a declared total. update() increments the counter and, when current exceeds total, warns. The warning is deliberately submitted to a dedicated single-thread executor because logging synchronously at that point would deadlock: log output itself flows through the progress rendering path. It means a ProgressLogger caller advanced progress more times than the total it declared, or declared the wrong total.","triggerScenarios":"A build operation calls progress/updated more often than the total it announced (e.g., a test executor declaring total=N but emitting N+1 progress events), two operations miscounting, or a wrong total computed before filtering. Typical for plugins or integrations driving the internal ProgressLogger API.","commonSituations":"Plugins misusing the ProgressLogger API; filtering logic making executed work exceed the precomputed total (e.g., test filtering); concurrent unguarded updates racing past the total.","solutions":["Cosmetic only: the bar exceeds 100% but nothing fails; safe to ignore if occasional.","Identify the offending operation: run with --console=plain or --info and note which progress operation passes its total.","Plugin authors: pass the exact total when creating the operation and call progress() at most total times; recompute totals after filtering.","Reproducible cases in Gradle's own progress reporting should be reported upstream with the operation name."],"exampleFix":"// before: declared total smaller than actual updates\nops.newOperation('copy')\n   .start('Copying files', files.size() - 1, false)\nfiles.each { op.progress() } // files.size() updates -> overflow\n\n// after: exact total\nops.newOperation('copy')\n   .start('Copying files', files.size(), false)","handlingStrategy":"validation","validationCode":"// compute the exact total from the same collection you iterate\nint total = files.size(); // not size() - 1, not a guess\nProgressLogger op = ops.newOperation('copy');\nop.start('Copying files', total, false);\nfor (File f : files) {\n    op.progress(); // called exactly `total` times\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Derive progress totals from the collection actually being iterated, after any filtering.","Never call progress() more times than the declared total; guard with a counter in test code.","Avoid concurrent unguarded progress() calls from multiple threads for one operation."],"tags":["gradle","console","progress-logger","off-by-one"],"backgroundTag":"progress-total-exceeded","analyzedSha":"534f27719b66953f95cc907aae7f2c1b12f5482d","analyzedAt":"2026-08-22T08:09:12.375Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}