{"record":{"id":"ecb84d8c391cd037","repo":"gradle/gradle","slug":"invalid-model-name-name-it-must-match-the-fo","errorCode":null,"errorMessage":"Invalid model name '${name}': it must match the following regular expression: [a-z]([a-zA-Z0-9])+","messagePattern":"Invalid model name '(.+?)': it must match the following regular expression: \\[a-z\\]\\(\\[a-zA-Z0-9\\]\\)\\+","errorType":"exception","errorClass":"InvalidUserDataException","httpStatus":null,"severity":"error","filePath":"platforms/software/dependency-management/src/main/java/org/gradle/internal/management/DefaultVersionCatalogBuilderContainer.java","lineNumber":64,"sourceCode":"    private final Supplier<DependencyResolutionServices> dependencyResolutionServices;\n    private final ObjectFactory objects;\n    private final UserCodeApplicationContext context;\n\n    @Inject\n    public DefaultVersionCatalogBuilderContainer(Instantiator instantiator,\n                                                 CollectionCallbackActionDecorator callbackActionDecorator,\n                                                 ObjectFactory objects,\n                                                 UserCodeApplicationContext context,\n                                                 Supplier<DependencyResolutionServices> dependencyResolutionServices) {\n        super(VersionCatalogBuilder.class, instantiator, callbackActionDecorator);\n        this.objects = objects;\n        this.context = context;\n        this.dependencyResolutionServices = dependencyResolutionServices;\n    }\n\n    private static void validateName(String name) {\n        if (!VALID_EXTENSION_PATTERN.matcher(name).matches()) {\n            throw new InvalidUserDataException(\"Invalid model name '\" + name + \"': it must match the following regular expression: \" + VALID_EXTENSION_NAME);\n        }\n    }\n\n    @Override\n    public VersionCatalogBuilder create(String name, Action<? super VersionCatalogBuilder> configureAction) throws InvalidUserDataException {\n        validateName(name);\n        return super.create(name, model -> {\n            UserCodeApplicationContext.Application current = context.current();\n            DefaultVersionCatalogBuilder builder = (DefaultVersionCatalogBuilder) model;\n            builder.withContext(current == null ? \"Settings\" : current.getSource().getDisplayName().getDisplayName(), () -> configureAction.execute(model));\n        });\n    }\n\n    @Override\n    protected VersionCatalogBuilder doCreate(String name) {\n        return objects.newInstance(DefaultVersionCatalogBuilder.class, name, strings, versions, objects, dependencyResolutionServices);\n    }\n","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/gradle/gradle/blob/534f27719b66953f95cc907aae7f2c1b12f5482d/platforms/software/dependency-management/src/main/java/org/gradle/internal/management/DefaultVersionCatalogBuilderContainer.java#L46-L82","documentation":"Version catalog names in Gradle must match the pattern [a-z]([a-zA-Z0-9])+ : they must start with a lowercase letter followed by one or more letters or digits. DefaultVersionCatalogBuilderContainer.validateName enforces this whenever a catalog is created via dependencyResolutionManagement.versionCatalogs.create(name). The restriction exists because the name becomes the accessor for the generated type-safe catalog (e.g. myLibs.some.dependency), so it must be a valid identifier prefix.","triggerScenarios":"Calling dependencyManagement { versionCatalogs { create('My-Libs') { } } } or any create(name) where name contains '-', '_', '.', or whitespace, starts with an uppercase letter, or starts with a digit. Also hit when a platform plugin derives the catalog name from a filename or user input without sanitizing it.","commonSituations":"Naming catalogs after teams or platforms with hyphens ('platform-libs'), capitalizing the first letter, or passing dynamic/generated names that slip in invalid characters.","solutions":["Rename the catalog to match [a-z][a-zA-Z0-9]* — e.g. 'myLibs' instead of 'my-libs'","Strip '-', '_', '.', spaces and leading digits when names come from user input or filenames","If a plugin generates the name, upgrade it or pass a compliant name explicitly"],"exampleFix":"// before:\ndependencyResolutionManagement {\n    versionCatalogs {\n        create('Platform-Libs') { from(files('gradle/libs.versions.toml')) }\n    }\n}\n// after:\ndependencyResolutionManagement {\n    versionCatalogs {\n        create('platformLibs') { from(files('gradle/libs.versions.toml')) }\n    }\n}","handlingStrategy":"validation","validationCode":"static boolean isValidCatalogName(String name) {\n    name != null && name ==~ /[a-z][a-zA-Z0-9]+/\n}\n// use before create:\nassert isValidCatalogName(catalogName) : \"catalog name '$catalogName' must match [a-z][a-zA-Z0-9]+\"","typeGuard":null,"tryCatchPattern":"try {\n    dependencyResolutionManagement.versionCatalogs.create(name) { from(files('gradle/libs.versions.toml')) }\n} catch (org.gradle.api.InvalidUserDataException e) {\n    throw new GradleException(\"Catalog name '$name' is invalid: must match [a-z][a-zA-Z0-9]+\", e)\n}","preventionTips":["Lowercase the first letter and strip '-', '_', '.' from catalog names","Sanitize names derived from filenames or environment variables before passing them to create()"],"tags":["gradle","version-catalog","naming","validation"],"backgroundTag":"invalid-identifier-name","analyzedSha":"534f27719b66953f95cc907aae7f2c1b12f5482d","analyzedAt":"2026-08-22T08:09:12.375Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}