Understanding the Problem

Symptoms

  • Infer runs successfully but reports zero issues on clearly defective code.
  • Different results when run locally vs in CI pipelines.
  • Errors like ERROR: captured no procedures or silent exits.
  • Significant slowdown or stalling on large Java/Objective-C projects.

Typical Context

This issue often arises in multi-module repositories, hybrid build systems (e.g., Make + Gradle), or when using custom wrapper scripts for Infer. Polyglot environments (Java/C++/Python) also trigger inconsistencies due to partial language support.

Root Causes

1. Improper Build Integration

Infer requires precise wrapping of the build command. If key compiler invocations are missed (e.g., in makefiles or scripts), Infer won't capture relevant procedures.

2. Incomplete Compilation Units

Infer analyzes the AST and intermediate code during compilation. If dependencies or include paths are skipped, the analyzer receives partial input and silently drops affected procedures.

3. Parallelism and Caching Conflicts

CI tools that aggressively parallelize builds may interfere with Infer's internal capture database. This can lead to incomplete or non-deterministic results.

4. Unsupported Language Constructs

Infer's support for C++, Java, and Objective-C is robust but not exhaustive. Advanced macros, template metaprogramming, or custom annotations may not be analyzed correctly.

5. Outdated Infer Version

Newer compilers introduce changes that older versions of Infer don't support, especially for C++17+ or Java 17+ codebases.

Diagnostics

Enable Debug Logs

infer --debug -- log.txt -- make clean all

Review log.txt for skipped files, parsing errors, or warnings.

Check Procedure Capture Count

Ensure Infer captures non-zero procedures:

infer capture -- make all
infer analyze

If Captured no procedures appears, revisit build integration.

Inspect Report Files

cat infer-out/report.json

Check if any bugs were reported or if the array is empty.

Run in Isolation

Try analyzing a single file or module to verify setup:

infer -- javac src/Example.java

Step-by-Step Fix

1. Properly Wrap the Build

Infer works by intercepting compiler commands. Use:

infer run -- make clean all

Or with Gradle:

infer -- ./gradlew clean build

2. Avoid Parallel Builds During Capture

Disable multi-threading to prevent missing procedures:

make -j1

Or use Infer's --jobs 1 flag.

3. Isolate Capture and Analyze Steps

Use explicit capture/analyze phases to debug:

infer capture -- make all
infer analyze

4. Upgrade Infer to the Latest Version

Older releases may not support newer Java/C++ standards. Always use the latest stable version from Facebook's GitHub repository.

5. Validate Include Paths and Dependencies

Ensure all header files, dependencies, and source paths are available during compilation. Use CPPFLAGS or JAVAC_OPTS as needed.

Architectural Implications

Build Tool Lock-In

Infer's design tightly couples it with the build process. This can cause friction in monorepos or with Bazel-like systems. Evaluate using JSON compilation databases or integration wrappers where feasible.

CI/CD Instability

Static analysis results that vary between local and CI environments reduce confidence and lead to code review friction. Standardizing build containers is essential.

Analysis Gaps in Polyglot Projects

Infer does not natively support Python, JavaScript, or Kotlin. Relying solely on Infer in mixed-language codebases leads to blind spots unless augmented with other tools.

Best Practices

  • Pin Infer versions and build environments to Docker images.
  • Always run infer capture with clean, full builds.
  • Use JSON output to integrate with dashboards and issue trackers.
  • Combine Infer with linters (e.g., ESLint, pylint) for full coverage.
  • Periodically validate results against seeded bugs for sanity checks.

Conclusion

Infer is a powerful static analyzer, but its effectiveness hinges on precise build integration and environment consistency. Teams often struggle with incomplete reports due to skipped procedures, unsupported language constructs, or misconfigured CI environments. By carefully structuring build commands, isolating analysis steps, and validating captured data, organizations can unlock Infer's full potential and elevate their code quality posture—especially in large, complex codebases.

FAQs

1. Why does Infer report no issues even with known bugs?

This usually means procedures were not captured. Check build integration and ensure a clean full build is used during capture.

2. Can Infer analyze Kotlin or JavaScript?

No. Infer only supports Java, C, C++, and Objective-C. Use supplementary tools for unsupported languages.

3. How can I speed up Infer analysis?

Use incremental analysis, reduce the codebase scope, or run only on changed modules during pre-merge checks.

4. How do I integrate Infer into GitHub Actions?

Use a Docker container with Infer preinstalled and wrap your build inside infer run. Upload report.json as an artifact or comment on pull requests.

5. Is Infer suitable for enterprise use?

Yes, if integrated correctly. It works best in consistent, build-driven environments and is highly effective when paired with code review automation.