Troubleshooting a Gradle Build Failure: Missing DoNotMock

A real-world case study of diagnosing and fixing a Gradle build failure caused by dependency conflicts in error_prone_annotations.

Troubleshooting a Gradle Build Failure: Missing DoNotMock

A real-world case study of diagnosing and fixing a Gradle build failure caused by dependency conflicts in error_prone_annotations.

Victory

Problem Description

After a project update, the build suddenly started failing with the following error:

error: cannot access DoNotMock
  class file for com.google.errorprone.annotations.DoNotMock not found

The project could not be built successfully anymore.

Problem Investigation

1. Review Recent Code Changes

The first step was to review the recent changes. No suspicious logic changes were found—only some updates to proto file definitions.

However:

  • Reverting the code fixed the build
  • Re-applying the changes broke it again

This confirmed that the issue was introduced by this update.

2. Identify the Root Cause from the Error

The error clearly indicated a missing class problem.

After some investigation, it turned out that:

The project originally depended on:

<dependency>
    <groupId>com.google.errorprone</groupId>
    <artifactId>error_prone_annotations</artifactId>
    <version>2.2.0</version>
</dependency>

3. Analyze Dependency Tree

To understand which version was actually used, the dependency tree was inspected:

./gradlew dependencies -q --configuration compile | grep error_prone_annotations -C 10

The output showed that error_prone_annotations 2.3.2 was being pulled in transitively by other dependencies (e.g., protobuf-java-util).

This version no longer contained DoNotMock, which caused the compilation failure.

Solutions

There are three possible solutions, depending on project constraints.

Force Gradle to use a version that still contains DoNotMock:

implementation('com.google.errorprone:error_prone_annotations:2.2.0') {
    force = true
}

Solution 2: Exclude the Conflicting Dependency

Exclude the newer error_prone_annotations from the dependency that introduces it:

compile("io.dropwizard.modules:dropwizard-protobuf:${dropwizardProtobufVersion}") {
    exclude group: 'com.google.errorprone', module: 'error_prone_annotations'
}

Upgrade all dependencies that rely on DoNotMock so they no longer reference it.

⚠️ This approach has the largest impact and requires careful verification.

Why This Happened

Although no direct dependency versions were changed, the update introduced gRPC-related code.

gRPC compilation pulled in additional dependencies, which in turn upgraded error_prone_annotations to a version incompatible with existing code.

error: cannot access DoNotMock
  class file for com.google.errorprone.annotations.DoNotMock not found

Summary

Key takeaways:

  • Transitive dependencies can silently introduce breaking changes
  • Always inspect the dependency tree when unexplained build errors occur
  • Forcing dependency versions is sometimes necessary in large projects
  • Small changes (like proto updates) can trigger deep dependency conflicts

This case highlights the importance of dependency awareness in modern Java builds.