ErrLookup › Background articles › InvalidUserDataException: Gradle's invalid-user-data build failure — malformed notations, missing properties, and validation errors explained

InvalidUserDataException: Gradle's invalid-user-data build failure — malformed notations, missing properties, and validation errors explained

InvalidUserDataException is the build-time error thrown when user-supplied input fails structural validation: malformed group:name:version or capability notations in useTarget(), useModule(), and dependency substitution; wrong version-catalog accessors; missing signing properties; colliding subproject accessor names; artifact transform outputs that are missing, absolute, or the wrong file/dir shape; and component metadata rules that assume variants the target does not publish. Elasticsearch's documentation build reuses the same class for REST-test snippet errors such as orphaned // TEST and // TESTRESPONSE markers, misplaced TESTSETUP directives, and response JSON that fails to parse. In every documented case the fix is to correct the build script, property, or snippet you wrote, not the tool.

Distilled from 223 documented records across 3 repositories.

Background

InvalidUserDataException is the build tool telling you that your input is wrong, as opposed to the tool, the network, or the environment failing. Every documented trigger in this family is a defect in something a person wrote: a coordinate string in a build script, a gradle.properties entry, a settings.gradle subproject name, or (in Elasticsearch) a documentation snippet marked with // CONSOLE, // TEST, or // TESTSETUP directives. The exception exists to fail fast at a trust boundary: before an invalid coordinate is written into a published .module file, before a transform output that was never created gets cached and consumed, and before a docs example ships without its generated REST test.

Mechanically the family has two territories. In Gradle core, notation parsers (ModuleComponentSelectorParsers, CapabilityNotationParserFactory, ParsedModuleStringNotation) reject strings that do not split into non-empty group, name, and version parts; model validators reject colliding project-accessor names (DefaultDependenciesAccessors), non-conforming version catalog names (DefaultVersionCatalogBuilderContainer), absent signing properties (PgpSignatoryFactory), and toolchain properties set to conflicting values in two scopes; DefaultTransformOutputs verifies that every registered transform output exists, sits inside the transform workspace, and matches its declared file or directory shape; and component metadata handling allows only String and Boolean attributes on the legacy ComponentMetadataBuilder path and requires a resolvable base variant for non-lenient addVariant rules. In Elasticsearch's docs build the same exception class enforces snippet grammar: directives must attach to an open snippet, TESTSETUP must be first in its file, // TEST[continued] cannot follow a setup or teardown snippet, TESTRESPONSE JSON must parse after variable substitution, and the converted/unconverted snippet accounting must match what the docs actually contain.

Timing varies within the family, which matters when debugging. Many checks fire eagerly at configuration or parse time, but several fire lazily: the flatDir empty-dirs check runs inside createRealResolver() only when a configuration is actually resolved, non-lenient addVariant(name, base) rules surface during metadata realisation rather than rule execution, and transform output validation runs only after the transform body returns. A build can therefore pass one phase and fail later, with the real cause sitting in an earlier declaration. From the caller's side it is always a hard build failure; the message usually names the offending value, often with a worked example of the expected format, or lists exactly which files, variants, or properties are at fault.

Treat the message text as a strong hint rather than a contract. The records document several message-level defects: the '// TEST[continued] cannot immediately follow // TEARDOWN' guard calls testSetup() where testTearDown() was presumably intended, so it fires under the TESTSETUP condition; the missing-teardown message embeds a literal, un-interpolated '$name'; the toolchain property message labels the system-property value as the 'Gradle property'; and the attribute-type message contains a typo ('have been provider by'). One record's guard on detached configurations reportedly raises InvalidUserCodeException rather than InvalidUserDataException, so the exact class is library- and code-path-specific. When a label contradicts what you know you wrote, verify against the source instead of assuming the message is right.

Common causes

What usually fixes it

Go deeper

Documented occurrences

…and 203 more across the corpus — use search.

Honest provenance: generated on 2026-08-22 from AI-assisted analysis of the linked records. See how records are made.