apereo/cas · error · GradleException

Missing required project metadata for

Error message

Missing required project metadata for ${projectName}

What it means

While generating project module metadata (for the CAS module/dependency catalog), build.gradle requires every publishable module to declare both 'title' and 'category' in its projectMetadata map; if either key is missing it throws GradleException("Missing required project metadata for ${projectName}").

Solutions

  1. Add 'title' and 'category' entries to the module's projectMetadata definition (see the metadata table in the build configuration).
  2. If the module shouldn't be published, set publishMetadata = false for it.
  3. Check for key typos and that the module path maps to the expected metadata entry.

Example fix

// before
projectMetadata = [selectable: true]
// after
projectMetadata = [title: 'CAS YubiKey Support', category: 'Authentication', selectable: true]
Defensive patterns

Strategy: validation

Validate before calling

// verify metadata keys before running metadata tasks
def md = moduleInfo.projectMetadata as Map
assert md.title && md.category : "module ${projectPath} needs title and category"

Type guard

static boolean hasRequiredMetadata(Map metadata) {
    return metadata?.containsKey('title') && metadata?.containsKey('category');
}

Prevention

When it happens

Trigger: Adding or renaming a module whose entry in the metadata map (moduleInfo.projectMetadata) lacks 'title' or 'category', then requesting generateProjectModulesMetadata / publishProjectModulesMetadata.

Common situations: Contributor creates a new module and forgets to add its metadata entry; a module is renamed so its metadata lookup misses; metadata file edited and a key typo'd as 'titel'/'catgeory'.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08). Data as JSON: /api/errors/954844c801b74986. Report an issue: GitHub.

Appendix: source

Thrown at build.gradle:344

}

def projectModulesMetadataTaskRequested = CasBuildSettings.isTaskRequested(project, 'generateProjectModulesMetadata') ||
    CasBuildSettings.isTaskRequested(project, 'publishProjectModulesMetadata')
if (projectModulesMetadataTaskRequested) {
    def modulesOutputFile = layout.buildDirectory.file('modules.json')
    def projectVersion = version.toString().replaceAll('-SNAPSHOT', '')
    def projectGroup = group.toString()
    def moduleMetadataResults = CasBuildSettings.includedProjectPaths(project)
        .findAll { projectPath -> projectPath != project.path }
        .collectMany { projectPath ->
            def moduleInfo = CasBuildSettings.projectModuleMetadata(project, projectPath)
            if (!moduleInfo.publishMetadata) {
                return []
            }
            def projectName = CasBuildSettings.projectNameFromPath(projectPath)
            def metadata = new LinkedHashMap<>(moduleInfo.projectMetadata as Map)
            if (!metadata.containsKey('title') || !metadata.containsKey('category')) {
                throw new GradleException("Missing required project metadata for ${projectName}")
            }
            if (!metadata.containsKey('selectable')) {
                metadata.put('selectable', true)
            }
            return [[
                name       : projectName,
                version    : projectVersion,
                group      : projectGroup,
                description: moduleInfo.description,
                details    : metadata
            ]]
        }
    def moduleMetadataJson = groovy.json.JsonOutput.toJson(moduleMetadataResults)

    def generateProjectModulesMetadata = tasks.register('generateProjectModulesMetadata') {
        outputs.file(modulesOutputFile)
        doLast {
            def output = modulesOutputFile.get().asFile

View on GitHub (pinned to e7288fc434)