apache/maven · error · RepositoryMetadataReadException

Cannot read metadata from '{}': {}

Error message

Cannot read metadata from '{}': {}

What it means

DefaultRepositoryMetadataManager.readMetadata() opens a maven-metadata.xml file with Files.newInputStream and parses it with a StAX reader; any IOException (permissions, truncated file, disk error) or XMLStreamException (malformed XML) is wrapped in RepositoryMetadataReadException with this message. The placeholders are the metadata file path and the underlying parser/IO message. A missing file is tolerated by callers, so this specifically means the file exists but cannot be read or parsed.

Source

Thrown at compat/maven-compat/src/main/java/org/apache/maven/artifact/repository/metadata/DefaultRepositoryMetadataManager.java:280

            } else {
                repoMetadata.setMetadata(metadata);
                setRepository = true;
            }
        }
        return setRepository;
    }

    /*
     * TODO share with DefaultPluginMappingManager.
     */
    protected Metadata readMetadata(File mappingFile) throws RepositoryMetadataReadException {

        try (InputStream in = Files.newInputStream(mappingFile.toPath())) {
            return new Metadata(new MetadataStaxReader().read(in, false));
        } catch (FileNotFoundException e) {
            throw new RepositoryMetadataReadException("Cannot read metadata from '" + mappingFile + "'", e);
        } catch (IOException | XMLStreamException e) {
            throw new RepositoryMetadataReadException(
                    "Cannot read metadata from '" + mappingFile + "': " + e.getMessage(), e);
        }
    }

    /**
     * Ensures the last updated timestamp of the specified metadata does not refer to the future and fixes the local
     * metadata if necessary to allow proper merging/updating of metadata during deployment.
     */
    private void fixTimestamp(File metadataFile, Metadata metadata, Metadata reference) {
        boolean changed = false;

        if (metadata != null && reference != null) {
            Versioning versioning = metadata.getVersioning();
            Versioning versioningRef = reference.getVersioning();
            if (versioning != null && versioningRef != null) {
                String lastUpdated = versioning.getLastUpdated();
                String now = versioningRef.getLastUpdated();
                if (lastUpdated != null && now != null && now.compareTo(lastUpdated) < 0) {

View on GitHub (pinned to e4093d4e12)

Solutions

  1. Delete the metadata file named in the message and rebuild with -U so Maven re-downloads it: rm ~/.m2/repository/<group>/<artifact>/maven-metadata*.xml
  2. Inspect the first lines of that file (head) for an HTML error page or truncated XML; if it came from a remote repository, purge that metadata on the repository manager too
  3. If the message is a permission or IO error, fix ownership/permissions on the local repository (chown -R) and check disk space
  4. If a CI cache ships the local repository, invalidate the cache after repairing so the corrupt file does not come back

Example fix

# before: corrupt file left in place, build fails on every run
head -3 ~/.m2/repository/com/example/art/maven-metadata.xml   # shows HTML or truncated XML
mvn clean install
# after: remove the corrupt metadata and force a refresh
rm ~/.m2/repository/com/example/art/maven-metadata*.xml
mvn -U clean install
Defensive patterns

Strategy: try-catch

Validate before calling

File f = new File(localRepository.getBasedir(),
        localRepository.pathOfLocalRepositoryMetadata(metadata, remoteRepository));
if (f.isFile()) {
    try {
        javax.xml.parsers.DocumentBuilderFactory.newInstance()
                .newDocumentBuilder().parse(f); // fails fast on corrupt XML
    } catch (Exception e) {
        // delete/repair the metadata file before resolving
    }
}

Try / catch

Catch RepositoryMetadataReadException around resolve()/resolveAlways()/deploy() call sites; treat it as a local-cache defect: delete the file named in the message and retry once, rethrow if it persists.

Prevention

When it happens

Trigger: Any metadata-consuming path that calls readMetadata(): resolveAlways(), deploy()'s retrieval of previous metadata, or snapshot/version metadata merging, when the local maven-metadata.xml is hand-edited into invalid XML, truncated by a killed build, zero bytes, an HTML error page cached by a mirror, or unreadable due to permissions or file locking.

Common situations: A build killed (Ctrl-C, CI timeout) while maven-metadata.xml is being written; a repository proxy returning an HTML 500 page that gets saved as metadata; antivirus or a read-only ~/.m2/repository; CI jobs caching a corrupt local repository between runs.

Related errors


AI-assisted analysis of apache/maven@e4093d4e12 (2026-08-21). Data as JSON: /api/errors/f9d5561770793456. Report an issue: GitHub.