SonarSource/sonarqube · error · IllegalArgumentException
Backup XML is not valid. Root element must be <profile>.
Error message
Backup XML is not valid. Root element must be <profile>.
What it means
QProfileParser.readXml validates the root element of an uploaded quality profile backup; the StAX cursor's first local name must be exactly 'profile'. Any other root element means the file is not a valid SonarQube profile backup and IllegalArgumentException is thrown.
Source
Thrown at server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileParser.java:134
.prop(ATTRIBUTE_PARAMETER_VALUE, param.getValue())
.end();
}
xml.end(ATTRIBUTE_PARAMETERS);
xml.end(ATTRIBUTE_RULE);
}
xml.end(ATTRIBUTE_RULES).end(ATTRIBUTE_PROFILE).close();
}
public ImportedQProfile readXml(Reader reader) {
List<ImportedRule> rules = new ArrayList<>();
String profileName = null;
String profileLang = null;
try {
SMInputFactory inputFactory = initStax();
SMHierarchicCursor rootC = inputFactory.rootElementCursor(reader);
rootC.advance(); // <profile>
if (!ATTRIBUTE_PROFILE.equals(rootC.getLocalName())) {
throw new IllegalArgumentException("Backup XML is not valid. Root element must be <profile>.");
}
SMInputCursor cursor = rootC.childElementCursor();
while (cursor.getNext() != null) {
String nodeName = cursor.getLocalName();
if (CS.equals(ATTRIBUTE_NAME, nodeName)) {
profileName = StringUtils.trim(cursor.collectDescendantText(false));
} else if (CS.equals(ATTRIBUTE_LANGUAGE, nodeName)) {
profileLang = StringUtils.trim(cursor.collectDescendantText(false));
} else if (CS.equals(ATTRIBUTE_RULES, nodeName)) {
SMInputCursor rulesCursor = cursor.childElementCursor("rule");
rules = parseRuleActivations(rulesCursor);
}
}
} catch (XMLStreamException e) {
throw new IllegalArgumentException("Fail to restore Quality profile backup, XML document is not well formed", e);
}
return new ImportedQProfile(profileName, profileLang, rules);View on GitHub (pinned to 184c821202)
Solutions
- Re-export the profile with GET api/qualityprofiles/backup?language=...&qualityProfile=... and restore that file unmodified.
- Edit the XML so the root element is <profile> if you intentionally restructured it.
- Validate the XML root locally before upload: parse and assert getDocumentElement().getTagName().equals("profile").
- Ensure you are not uploading an export of ALL profiles where the expected single-profile root differs.
Example fix
// before
restoreProfile(readFile("profiles.xml")); // root is <profiles>
// after
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File("profiles.xml"));
if (!"profile".equals(doc.getDocumentElement().getTagName())) {
throw new IllegalStateException("not a single-profile backup file");
}
restoreProfile(new ByteArrayInputStream(serialized(doc))); Defensive patterns
Strategy: validation
Validate before calling
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputStream);
if (!"profile".equals(doc.getDocumentElement().getTagName())) {
throw new IllegalStateException("backup root element must be <profile>");
} Type guard
static boolean isProfileBackup(File f) throws Exception {
Document d = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(f);
return "profile".equals(d.getDocumentElement().getTagName());
} Try / catch
try {
restoreProfile(stream);
} catch (SonarQubeClientException e) {
if (String.valueOf(e.getMessage()).contains("Root element must be <profile>")) {
LOG.error("file is not a single-profile backup; re-export via api/qualityprofiles/backup");
}
throw e;
} Prevention
- Always obtain backups from GET api/qualityprofiles/backup and restore them unmodified
- Validate the root element locally before any upload
- Beware BOM/encoding issues when editing XML by hand
When it happens
Trigger: POST api/qualityprofiles/restore with XML whose root element is <profiles>, <qualityProfile>, or anything other than <profile>; uploading a truncated or wrapped XML file; posting HTML/JSON error pages saved as XML.
Common situations: Hand-edited backups; files concatenated or wrapped by an aggregation step; downloading the wrong endpoint (a list of profiles rather than a single profile export); character-set/BOM issues that break root detection.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Fail to restore Quality profile backup, XML document is not
- The quality profile cannot be restored as it contains duplic
- Unknown severity: %s
- Transition '%s' not supported. Only %s are supported.
- Failed to set the New Code Definition. The given value is no
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/95e14ea5f784d689.
Report an issue: GitHub.