Skip to content

[SPARK-56630][INFRA] Surface javadoc crash culprit in unidoc failure output#55548

Closed
cloud-fan wants to merge 4 commits into
apache:masterfrom
cloud-fan:javadoc-error-reporting
Closed

[SPARK-56630][INFRA] Surface javadoc crash culprit in unidoc failure output#55548
cloud-fan wants to merge 4 commits into
apache:masterfrom
cloud-fan:javadoc-error-reporting

Conversation

@cloud-fan
Copy link
Copy Markdown
Contributor

What changes were proposed in this pull request?

Adds a diagnostic banner to the unidoc step in docs/_plugins/build_api_docs.rb. When build/sbt unidoc fails, the script now scans the captured sbt output and prints a framed summary naming the <Class>.html javadoc was generating when it died, the inferred source class to audit, and a one-paragraph hint about the usual scaladoc triggers.

Implementation:

  • stream_and_capture tees sbt output to both stdout and target/unidoc-build.log (Ruby-only, no shell pipefail reliance).
  • diagnose_unidoc_failure finds the last Generating .../<Class>.html... line before javadoc exited with exit code N and prints a culprit-pointer banner. ANSI colour codes are stripped before regex matching.
  • When the failure mode doesn't match the mid-HTML-crash pattern (e.g. scaladoc failure, sbt env issue), the banner says so and points back to the full log.

Why are the changes needed?

Today, when javadoc hard-exits during unidoc HTML generation -- typically because of a specific scaladoc construct (e.g. wiki-style [[Class]] links or backtick-inline code refs) in an exposed Scala source -- the failing PR's CI log shows ~100 [error] lines on target/java/... files. Those errors are benign: they're genjavadoc-emitted Java stubs (static public abstract R apply(T1, T2, T3, T4)) that every PR produces, and javadoc always complains about them but normally still finishes. They are not the cause of the failure.

The actual signal is the last Generating .../<Class>.html... line before javadoc exited with exit code 1, which a developer has to find by hand in a multi-thousand-line log. The error reporting does not differentiate the benign noise from the real crash, so the failure consistently looks like it's "in" ErrorInfo.java / LexicalThreadLocal.java / similar, when it's actually in a Scala source that none of those names point to.

A recent example: PR #51419 hit this exact misdirection -- the log was full of errors on common/utils/target/java/... stubs, but the real culprit was a doc comment in CatalogV2Implicits.IdentifierHelper that triggered a hard exit during HTML generation. The diagnostic in this PR would have named that class directly.

Does this PR introduce any user-facing change?

No. CI-only output change visible in the unidoc step of the doc-gen job.

How was this patch tested?

  • Dry-ran the parser logic against the captured failing log from PR [SPARK-52729][SQL] Add MetadataOnlyTable and CREATE/ALTER VIEW support for DS v2 catalogs #51419 -- it correctly extracts org/apache/spark/sql/connector/catalog/CatalogV2Implicits.IdentifierHelper.html as the crash class.
  • The second commit on this branch (DO NOT MERGE: break a docstring to validate the unidoc diagnostic) intentionally reintroduces the same [[...]]+backtick-inline scaladoc pattern in CatalogV2Implicits.IdentifierHelper.asTableIdentifierOpt so that this PR's CI run actually exercises the new path. Once the banner fires and names that class on the failing CI run, that commit will be dropped from this PR.

Was this patch authored or co-authored using generative AI tooling?

Generated-by: Claude (Anthropic)

Unidoc currently fails with ~100 `[error]` lines on genjavadoc-generated
Java stubs under `target/java/...` (private Scala case-class `apply`
methods that produce invalid `static public abstract R apply(T1, ...)`
Java). These errors are benign -- every PR emits them -- but they
overshadow the real cause when javadoc hard-exits mid-stream on specific
doc-comment content. The actual crash signal is the last
`Generating .../<Class>.html...` line before
`javadoc exited with exit code 1`, which a developer has to hunt for by
hand in multi-thousand-line CI logs.

Tee sbt output to `target/unidoc-build.log` and, on failure, print a
framed banner with:
  - the HTML file javadoc was generating when it died,
  - the inferred source class to audit,
  - a one-paragraph hint about the usual scaladoc triggers
    (wiki-style `[[...]]` links, inline-backtick code refs),
  - an explicit note that the `[error]` lines on `target/java/...`
    stubs are not the cause.

Heuristic only; when the log doesn't match the mid-HTML-crash pattern
(e.g. scaladoc failure, sbt env issue) the banner says so and points
back to the full log above.

Co-authored-by: Isaac
Intentionally reintroduces the scaladoc pattern that hard-exited
javadoc on PR apache#51419 (wiki-style [[TableIdentifier]] /
[[toQualifiedNameParts]] refs plus backtick-inline `Seq[String]`)
in CatalogV2Implicits.IdentifierHelper. CI should fail at the unidoc
step and the new diagnostic banner should name this class as the
culprit. Drop this commit before merging.

Co-authored-by: Isaac
@cloud-fan
Copy link
Copy Markdown
Contributor Author

The bait commit on this branch (a4b30e83a3dDO NOT MERGE: break a docstring) successfully exercised the new diagnostic in CI on the latest run. Captured banner from the failing Run / Documentation generation job (log):

==============================================================================
Unidoc failed -- diagnostic summary
==============================================================================

  Javadoc crashed while generating: org/apache/spark/sql/connector/catalog/CatalogV2Implicits.IdentifierHelper.html
  Likely culprit: doc comment in org.apache.spark.sql.connector.catalog.CatalogV2Implicits.IdentifierHelper

  Javadoc can hard-exit (not just warn) on specific scaladoc
  patterns once they have been passed through genjavadoc --
  wiki-style `[[Class]]` / `[[method]]` links or inline-backticked
  code refs in the Scala source for the class above are common
  triggers. Start by auditing any recent doc-string changes in
  that source file.

  NOTE: the '[error]' lines above on files under
  target/java/... are benign genjavadoc stubs -- every PR
  emits them and they do not cause the exit. Ignore them.
==============================================================================

The banner correctly named CatalogV2Implicits.IdentifierHelper — the exact class the bait commit broke — instead of leaving the reader to scroll past ~100 benign [error] lines on target/java/... stubs. Reverting the bait commit next.

@cloud-fan cloud-fan marked this pull request as ready for review April 26, 2026 10:42
@HyukjinKwon
Copy link
Copy Markdown
Member

Merged to master.

juliuszsompolski pushed a commit to juliuszsompolski/apache-spark that referenced this pull request Apr 28, 2026
…ilures

The unidoc step in CI sometimes failed with the SPARK-56630
(apache#55548) banner reporting "Javadoc
exited but no class HTML generation was in progress" or with no
actionable diagnostic at all. Two javadoc defaults were masking the
underlying causes:

1. `-Xmaxerrs 100`: javadoc bails during source loading once the
   cumulative count of benign genjavadoc-stub errors crosses 100, before
   any HTML is generated. Every Spark unidoc run produces ~100 such
   errors (`error: cannot find symbol` on type variables, `error: illegal
   combination of modifiers: abstract and static`) -- the SPARK-56630 PR
   description documents that these are inert. When the count tips past
   100 the build fails with a wall of those errors and no Generating
   .html line for the SPARK-56630 banner to point at.

2. `-Xmaxwarns 100`: even when javadoc completes HTML generation, the
   doclint warnings on a full Spark unidoc run number in the tens of
   thousands (`no comment`, `empty <p> tag`, `no @return`, `no @param
   ...`). Anything past the first 100 is silently dropped, including
   per-link `error: reference not found` lines that share the warn
   stream.

Setting both ceilings to 999999 keeps javadoc producing output past the
real volume so the SPARK-56630 banner can identify the crashing class.

`-verbose` makes javadoc emit a `<path>.java:<line>: error: reference
not found` line for every broken {@link} during HTML generation. Without
it, javadoc tracks reference errors in its internal counter and reports
the bulk total in the final `<N> errors / <M> warnings` summary, but
does not print a file:line for each one. The flag also dumps "Loading
source file ..." progress lines and grows the unidoc log by an order of
magnitude; that is the price of being able to debug reference errors at
all from CI logs.

This change does not silence any failure -- javadoc still exits non-zero
when there are real errors. It only removes the noise / clipping masks.
juliuszsompolski pushed a commit to juliuszsompolski/apache-spark that referenced this pull request Apr 28, 2026
The diagnostic banner added in SPARK-56630
(apache#55548) names the class javadoc was
rendering when it crashed mid-HTML-generation. With -verbose now enabled
in JavaUnidoc / unidoc / javacOptions, javadoc also emits a per-error
line of the form

    <path>.java:<line>: error: reference not found

for every broken {@link} it can't resolve during HTML generation, and
the build then fails on the non-zero error count even though all HTML
files were produced. This commit makes the banner scan the captured log
for those messages and list them in the diagnostic output, so the
developer sees the file:line of each broken {@link} alongside the
existing class-crash hint.

A short note on the most common cause is included in the banner:
[[Class.member]] in scaladoc when Class is a regular class/trait (not a
Scala object) trips javadoc's inner-class lookup; the fix is to use
[[Class#member]] (the Javadoc-canonical member separator), which
genjavadoc passes through unchanged.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants