bazelbuild/bazel · error · RuntimeError

Proguard failed ( )

Error message

Proguard failed ({p.returncode})

What it means

Raised by the proguard wrapper after running the proguard subprocess with check=False and observing a non-zero exit code. The RuntimeError message embeds p.returncode plus any decoded stdout and stderr, so the underlying proguard diagnostics travel with the exception.

Solutions

  1. Read the embedded stderr in the message — proguard's own diagnostics name the exact offending rule or class.
  2. Add the missing jars to the deps argument so proguard can resolve referenced classes.
  3. Fix or remove the offending -keep/-assumenosideeffects entry in the proguard spec.
  4. If version-related, align the proguard spec dialect with the proguard binary shipped in the wrapper's runfiles.

Example fix

# before
apply_proguard(srcs=["a.jar"], deps=[], proguard_spec="spec.pro", ...)
# spec.pro: -keep class com.example.Missing { *; }

# after
apply_proguard(srcs=["a.jar"], deps=["missing.jar"], proguard_spec="spec.pro", ...)
Defensive patterns

Strategy: try-catch

Validate before calling

for j in srcs + deps:
    assert os.path.exists(j), 'missing jar for proguard: %s' % j

Try / catch

try:
    apply_proguard(srcs, deps, spec, out)
except RuntimeError as e:
    # message embeds returncode, stdout, stderr of proguard
    log_error('proguard failure', details=str(e))
    raise

Prevention

When it happens

Trigger: apply_proguard() invoked with source jars, dep jars, or a spec that proguard rejects: missing classes referenced by -keep rules, malformed .pro file syntax, duplicate class files, or incompatible proguard version.

Common situations: A -keep class references a class not in the inputs; deps list incomplete so proguard cannot resolve the classpath; spec file contains options unsupported by the shipped proguard version.

Related errors


AI-assisted analysis of bazelbuild/bazel@e6e199d060 (2026-08-14). Data as JSON: /api/errors/9eb1482285033ed5. Report an issue: GitHub.

Appendix: source

Thrown at tools/build_defs/proguard/wrapper.py:101

      "-outjars",
      output_jar,
      "@" + proguard_spec,
  ]

  env = os.environ.copy()
  env.update(r.EnvVars())
  # print("Running proguard: %s" % " ".join(command))
  p = subprocess.run(command, capture_output=True, env=env, check=False)

  if p.returncode != 0:
    message = f"Proguard failed ({p.returncode})"
    stdout = p.stdout.decode()
    if stdout:
      message += f"\n  stdout:\n{stdout}"
    stderr = p.stderr.decode()
    if stderr:
      message += f"\n  stderr:\n{stderr}"
    raise RuntimeError(message)


def reset_timestamps(input_jar, output_jar, timestamp):
  """Rewrite the given jar file to reset all timestamps to a known value.

  Args:
    input_jar: The jar file to be modified.
    output_jar: The path to write the destination jar to.
    timestamp: The known timestamp to modify the output_jar with.
  """
  # print("Resetting timestamps in %s to %s, writing to %s" % (input,
  # timestamp, output))

  with zipfile.ZipFile(input_jar, mode="r") as src:
    with zipfile.ZipFile(output_jar, mode="w") as dest:
      for info in src.infolist():
        # print(f"Filename: {info.filename}")
        # print(f"  Modified: {datetime.datetime(*info.date_time)}")

View on GitHub (pinned to e6e199d060)