SonarSource/sonarqube · error · SarifDeserializationException

SYNTAX

SYNTAX

Error message

Failed to read SARIF report at '%s': %s

What it means

SonarQube's SARIF importer wraps Jackson's JsonParseException into SarifDeserializationException with Category.SYNTAX when the report file at reportPath is not valid JSON (malformed syntax: stray characters, truncation, truncated/unterminated strings or brackets). The message 'Failed to read SARIF report at %s: %s' embeds the path and Jackson's own parse-error description (often with line/column). It is thrown from SarifSerializerImpl.deserialize so callers can classify import failures by category.

Source

Thrown at sonar-core/src/main/java/org/sonar/core/sarif/SarifSerializerImpl.java:88

  @Override
  public SarifSchema210 deserialize(Path reportPath) {
    try {
      return mapper
        .enable(JsonParser.Feature.INCLUDE_SOURCE_IN_LOCATION)
        .addHandler(new DeserializationProblemHandler() {
          @Override
          public Object handleInstantiationProblem(DeserializationContext ctxt, Class<?> instClass, Object argument, Throwable t) throws IOException {
            if (!instClass.equals(SarifSchema210.Version.class)) {
              return NOT_HANDLED;
            }
            throw new UnsupportedSarifVersionException(format(UNSUPPORTED_VERSION_MESSAGE_TEMPLATE, argument), t);
          }
        })
        .readValue(reportPath.toFile(), SarifSchema210.class);
    } catch (UnsupportedSarifVersionException e) {
      throw new SarifDeserializationException(Category.MAPPING, e.getMessage(), e);
    } catch (JsonParseException e) {
      throw new SarifDeserializationException(Category.SYNTAX, format(SARIF_REPORT_ERROR, reportPath, e.getMessage()), e);
    } catch (JsonMappingException e) {
      if (e.getMessage() != null && (e.getMessage().contains("out of range") || e.getMessage().contains("overflow"))) {
        throw new SarifDeserializationException(Category.VALUE, format(SARIF_REPORT_ERROR, reportPath, e.getMessage()), e);
      }
      throw new SarifDeserializationException(Category.MAPPING, format(SARIF_REPORT_ERROR, reportPath, e.getMessage()), e);
    } catch (FileNotFoundException e) {
      throw new SarifDeserializationException(Category.FILE_NOT_FOUND, format(SARIF_REPORT_ERROR, reportPath, e.getMessage()), e);
    } catch (IOException e) {
      throw new IllegalStateException(format(SARIF_REPORT_ERROR, reportPath, e.getMessage()), e);
    }
  }

  private static class UnsupportedSarifVersionException extends IOException {

    public UnsupportedSarifVersionException(String message, Throwable t) {
      super(message, t);
    }
  }

View on GitHub (pinned to 184c821202)

Solutions

  1. Open the report at the path in the message and validate it with a JSON linter/parser (e.g. `jq . report.sarif`) to find the exact line/column Jackson reports
  2. Re-export or re-download the SARIF report from the producing tool; verify the download completed (compare file size/checksum)
  3. Verify the path passed to deserialize()/sonar.sarifReportPaths points to the actual SARIF JSON file, not a log, HTML page, or directory listing
  4. Ensure the file is UTF-8 encoded without BOM and was not truncated by the transfer

Example fix

// before
SarifSchema210 sarif = sarifSerializer.deserialize(reportPath); // throws SYNTAX on corrupt file
// after
byte[] bytes = java.nio.file.Files.readAllBytes(reportPath);
try (var parser = new com.fasterxml.jackson.core.JsonFactory().createParser(bytes)) {
  while (parser.nextToken() != null) { } // fail fast with Jackson's line/column if invalid
}
SarifSchema210 sarif = sarifSerializer.deserialize(reportPath);
Defensive patterns

Strategy: validation

Validate before calling

boolean isValidJsonFile(Path p) throws IOException {
  if (!Files.isRegularFile(p)) return false;
  try (com.fasterxml.jackson.core.JsonParser parser = new com.fasterxml.jackson.core.JsonFactory()
      .createParser(Files.newBufferedReader(p, StandardCharsets.UTF_8))) {
    while (parser.nextToken() != null) { }
    return true;
  } catch (com.fasterxml.jackson.core.JsonParseException e) {
    return false;
  }
}

Type guard

boolean isReadableSarif(Path p) {
  return Files.isRegularFile(p) && Files.size(p) > 0
    && p.getFileName().toString().matches("(?i).*\\.sarif(json)?$");
}

Try / catch

try {
  SarifSchema210 sarif = serializer.deserialize(reportPath);
} catch (SarifDeserializationException e) {
  if (e.getCategory() == Category.SYNTAX) {
    LOG.error("SARIF report is not valid JSON: {}", reportPath); // skip or re-export
  } else throw e;
}

Prevention

When it happens

Trigger: Calling SarifSerializer.deserialize(Path) (directly or via SARIF report import in SonarQube) on a file whose content is not syntactically valid JSON — e.g. an HTML error page saved as .sarif, a truncated download, a file containing BOM/prose, or an empty file that Jackson reports as 'No content to map due to end-of-input'.

Common situations: CI artifact upload corrupted or truncated the SARIF file; a tool wrote a non-JSON log to the SARIF path; user pointed sonar.sarifReportPaths at the wrong file; file downloaded via HTTP where the server returned an error page with 200; file encoding issues (UTF-16 SARIF read as UTF-8).

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/5bfc2762dfe70185. Report an issue: GitHub.