When reporting a structured problem with Gradle's Problems API, what severity levels can you assign via the ProblemSpec, and what does each one mean for the build?
answer
- Severity enum: ADVICE / WARNING / ERROR
- spec.severity(Severity.X)
- report() records, does NOT fail
- throwing() records AND fails
- severity is metadata, not control flow
basics
~20 sSeverity is set with spec.severity(...) using the Severity enum: WARNING, ERROR, and ADVICE. ERROR signals a real failure, WARNING a concern, and ADVICE a hint/suggestion. It classifies the problem; it does not by itself fail the build.
solid answer
~40 sGradle's Problems API lets a plugin attach a `Severity` to each reported problem through the `ProblemSpec.severity(Severity)` call. The enum has three members: `ADVICE` (a gentle hint, e.g. a deprecation-style nudge), `WARNING` (something the user should look at but the build can continue), and `ERROR` (a genuine fault). Severity is metadata for consumers — IDEs and the HTML problems report group and colour problems by it. Crucially, `severity(ERROR)` alone does **not** fail the build: reporting via `problems.getReporter().report(...)` only records the problem. To both record *and* fail you call `reporter.throwing(...)` with a `RuntimeException`, which emits the structured problem and then throws. So severity describes how serious the problem is, while the choice of `report` vs `throwing` decides whether the build stops.
code
kotlin · 5 linesreporter.report(problemId) { spec ->
spec.severity(Severity.ERROR)
.details("Plugin 'foo' requires Java 17+")
}
// NOTE: this records an ERROR-severity problem but the build still continues.go deeper
Name the three enum values and say severity classifies how serious the problem is.
Add that report() records while throwing() fails the build, so ERROR alone doesn't stop anything.
Explain why typed severity beats log-string scraping for IDE/Tooling-API consumers, and that it drives grouping in the HTML report.
Frame severity as part of a stable diagnostic contract across console, HTML report, and Tooling API — pushing teams off ad-hoc logger.warn toward consumable diagnostics.
## What the Problems API is Gradle's **Problems API** (incubating, stabilising across Gradle 8.x) is a way for plugins and tasks to emit **structured diagnostics** instead of plain `logger.warn("...")` strings. A structured problem carries a category/id, a label, a severity, optional source locations, optional solutions, and a documentation link. Build tools and IDEs (via the Tooling API) consume these objects programmatically — so an IDE can show a clickable, categorised warning rather than scraping console text. You obtain the entry point by injecting `org.gradle.api.problems.Problems`, then `problems.getReporter()` gives a `ProblemReporter`. You describe a problem with a configuration lambda over a `ProblemSpec`. ## The Severity enum `org.gradle.api.problems.Severity` has exactly three constants: - **`ADVICE`** — a suggestion or hint. Lowest urgency; "you might prefer to do X". - **`WARNING`** — something is off but the build can still proceed. - **`ERROR`** — a genuine fault. You attach it with `spec.severity(Severity.WARNING)`. If you never call `severity(...)`, the problem still reports with a default. ## Severity does not control build failure This is the key gotcha. Reporting a problem records it; it never stops the build on its own — **even with `Severity.ERROR`**. There are two reporter methods: - `reporter.report(ProblemId, spec)` (or the id-via-spec overload) — record only, build continues. - `reporter.throwing(exception, ...)` — record the structured problem **and** throw the supplied exception, failing the build. So `ERROR` is a *classification*; `throwing` is the *action*. Treating `severity(ERROR)` as "this fails the build" is the classic mistake. ```kotlin val problems = project.serviceOf<Problems>() // or @Inject in a task/plugin val reporter = problems.reporter val id = ProblemId.create("missing-config", "Missing configuration", myGroup) reporter.report(id) { spec -> spec.severity(Severity.WARNING) .details("The 'apiKey' property was not set") } ``` ## Why structured severity matters to consumers The HTML **problems report** and IDE integrations bucket problems by severity, render colour/icons, and let users filter. Because the severity is a typed enum rather than a substring of a log line, consumers stay robust as wording changes.
- If severity(ERROR) doesn't fail the build, how do you both report a structured problem and stop the build?Use reporter.throwing(...) passing a RuntimeException — it emits the structured problem and then throws, failing the build. report(...) only records.
- What is the default severity if you never call severity()?The problem still gets a default severity (WARNING in current Gradle), but you should set it explicitly to be unambiguous for consumers.
saying these in an interview costs you the question
- Claiming Severity.ERROR automatically fails the build — it does not; report() only records.
- Inventing extra levels like INFO/FATAL/CRITICAL — there are exactly three: ADVICE, WARNING, ERROR.