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

  1. Validate the JSON with a parser before sending (JSON.parse / jq) and fix syntax errors
  2. Send the value properly form-encoded so quotes survive transport
  3. 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

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


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)