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
- 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
- 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
- If the message is a permission or IO error, fix ownership/permissions on the local repository (chown -R) and check disk space
- 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
- Never hand-edit maven-metadata.xml files; let Maven write them.
- Exclude maven-metadata*.xml from CI caches of the local repository, or validate cached repositories before reuse.
- After killing a build, delete partially written maven-metadata.xml files before the next run.
- Keep the local repository writable and not locked/scanned by antivirus.
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
- Error installing metadata: {}
- Failed to parse plugin descriptor for ${plugin.getId()} (${d
- Unable to read model:
- Range defies version ordering: {}
- {} could not be retrieved from repository: {} due to an erro
AI-assisted analysis of apache/maven@e4093d4e12 (2026-08-21).
Data as JSON: /api/errors/f9d5561770793456.
Report an issue: GitHub.