SonarSource/sonarqube · error · IllegalArgumentException
Provided JSON is invalid
Error message
Provided JSON is invalid
What it means
SettingValidations.validateJson parses the submitted value as JSON with Gson before storing a JSON-typed setting. If Gson raises JsonParseException (or reading the content fails with IOException), the value is not valid JSON and IllegalArgumentException("Provided JSON is invalid") is thrown, surfaced as a 400 from the web API.
Solutions
- Validate the JSON with a parser before sending (JSON.parse / jq) and fix syntax errors
- Send the value properly form-encoded so quotes survive transport
- If it is a SECURITY_JSON_PROPERTIES key, additionally confirm the payload matches the setting's JSON schema
Example fix
// before
curl -d 'key=sonar.xxx' -d 'value={a:1}' ... # not valid JSON
// after
curl -d 'key=sonar.xxx' --data-urlencode 'value={"a":1}' ... Defensive patterns
Strategy: validation
Validate before calling
function isValidJson(s) { try { JSON.parse(s); return true; } catch { return false; } }
if (!isValidJson(value)) throw new Error('Fix JSON before calling api/settings/set'); Type guard
function asJsonObject(s) { try { return { ok: true, value: JSON.parse(s) }; } catch { return { ok: false }; } } Try / catch
try { await setSetting(key, json); } catch (e) { if (/Provided JSON is invalid$/.test(e.message)) { console.error('Payload is not parseable JSON'); } throw e; } Prevention
- Run the payload through JSON.parse or jq before sending
- Always use --data-urlencode or a JSON body so quotes survive shell/HTTP encoding
- Avoid hand-writing JSON in shell scripts; generate it with a serializer
When it happens
Trigger: POST api/settings/set on a JSON-typed setting (definition.type == JSON) where the value string is malformed, e.g. missing quotes, trailing comma, single quotes, or truncated payload.
Common situations: Copy-pasting JSON with smart quotes from docs, shell quoting stripping double quotes, truncation when the value is passed via form-encoded parameters, or templating engines mangling braces.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
Related errors
- Field ' ' is not sortable
- For security reasons, the key
- new_password_same_as_old
- Provided JSON is invalid
- ' ' and ' ' cannot be used at the same time as they refer…
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/8603f0e71f5c7158.
Report an issue: GitHub.
Appendix: source
Thrown at server/sonar-webserver-webapi/src/main/java/org/sonar/server/setting/ws/SettingValidations.java:203
});
}
private void validateLogin(SettingData data) {
try (DbSession dbSession = dbClient.openSession(false)) {
List<UserDto> users = dbClient.userDao().selectByLogins(dbSession, data.values).stream().filter(UserDto::isActive).toList();
checkRequest(data.values.size() == users.size(), "Error when validating login setting with key '%s' and values [%s]. A value is not a valid login.",
data.key, String.join(", ", data.values));
}
}
private void validateJson(SettingData data, PropertyDefinition definition) {
Optional<String> jsonContent = data.values.stream().findFirst();
if (jsonContent.isPresent()) {
try {
new Gson().getAdapter(JsonElement.class).fromJson(jsonContent.get());
validateJsonSchema(jsonContent.get(), definition);
} catch (JsonParseException | IOException e) {
throw new IllegalArgumentException("Provided JSON is invalid");
}
}
}
private void validateJsonSchema(String json, PropertyDefinition definition) {
if (SECURITY_JSON_PROPERTIES.contains(definition.key())) {
JsonValue jsonToValidate = new JsonParser(json).parse();
Optional.ofNullable(schemaValidator.validate(jsonToValidate))
.ifPresent(validationFailure -> {
ValidationFailure rootCause = getRootCause(validationFailure);
throw new IllegalArgumentException(String.format("Provided JSON is invalid : [%s at %s]", rootCause.getMessage(), rootCause.getInstance().getLocation()));
});
}
}
private static ValidationFailure getRootCause(ValidationFailure base) {
return base.getCauses().stream()
.map(ValueTypeValidation::getRootCause)View on GitHub (pinned to 184c821202)