{"record":{"id":"1507d1abb44a275c","repo":"SonarSource/sonarqube","slug":"unexpected-response-from-bitbucket-server","errorCode":null,"errorMessage":"Unexpected response from Bitbucket server","messagePattern":"Unexpected response from Bitbucket server","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"server/sonar-alm-client/src/main/java/org/sonar/alm/client/bitbucketserver/BitbucketServerRestClient.java","lineNumber":178,"sourceCode":"  }\n\n  protected static <G> G applyHandler(Function<String, G> handler, String bodyString) {\n    try {\n      return handler.apply(bodyString);\n    } catch (JsonSyntaxException e) {\n      LOG.info(UNABLE_TO_CONTACT_BITBUCKET_SERVER + \". Unexpected body response was : [{}]\", bodyString);\n      LOG.info(UNABLE_TO_CONTACT_BITBUCKET_SERVER + \": {}\", e.getMessage(), e);\n      throw new IllegalArgumentException(UNABLE_TO_CONTACT_BITBUCKET_SERVER + \", got an unexpected response\", e);\n    }\n  }\n\n  protected static void validateResponseBody(boolean isSuccessful, String bodyString) {\n    if (isSuccessful) {\n      try {\n        buildGson().fromJson(bodyString, Object.class);\n      } catch (JsonParseException e) {\n        LOG.info(UNEXPECTED_RESPONSE_FROM_BITBUCKET_SERVER + \" : [{}]\", bodyString);\n        throw new IllegalArgumentException(UNEXPECTED_RESPONSE_FROM_BITBUCKET_SERVER, e);\n      }\n    }\n  }\n\n  protected static void handleHttpErrorIfAny(boolean isSuccessful, int httpCode, String bodyString) {\n    if (!isSuccessful) {\n      String errorMessage = getErrorMessage(bodyString);\n      LOG.info(UNABLE_TO_CONTACT_BITBUCKET_SERVER + \": {} {}\", httpCode, errorMessage);\n      if (httpCode == HTTP_UNAUTHORIZED) {\n        throw new BitbucketServerException(HTTP_UNAUTHORIZED, \"Invalid personal access token\");\n      } else if (httpCode == HTTP_NOT_FOUND) {\n        throw new BitbucketServerException(HTTP_NOT_FOUND, \"Error 404. The requested Bitbucket server is unreachable.\");\n      }\n      throw new IllegalArgumentException(UNABLE_TO_CONTACT_BITBUCKET_SERVER);\n    }\n  }\n\n  protected static boolean equals(@Nullable MediaType first, @Nullable MediaType second) {","sourceCodeStart":160,"sourceCodeEnd":196,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-alm-client/src/main/java/org/sonar/alm/client/bitbucketserver/BitbucketServerRestClient.java#L160-L196","documentation":"validateResponseBody runs on successful (2xx) responses before the handler: it parses the body as a generic Gson Object to prove it is valid JSON. If parsing throws JsonParseException, the client throws IllegalArgumentException('Unexpected response from Bitbucket server') — the server replied 200 OK with a non-JSON body.","triggerScenarios":"An HTTP 200 response whose body is not JSON at all — e.g. an HTML SSO login page, a proxy maintenance page, or gzip/charset mangling — detected while calling any Bitbucket REST endpoint via getBodyString.","commonSituations":"SSO/SSO plugins redirecting REST calls to an HTML login form with 200 status; transparent proxies or load balancers serving error/maintenance HTML; misconfigured URL pointing to a web app root instead of the Bitbucket API host.","solutions":["Inspect the logged body '[...]' in the server log to identify what the 200 response actually contained.","Fix the server URL so REST calls hit Bitbucket directly rather than an SSO or proxy page.","Bypass the SSO/proxy for SonarQube (IP allowlist or service account) so REST endpoints return JSON.","Check proxy/load-balancer health-page behavior for the configured host."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  // call client\n} catch (IllegalArgumentException e) {\n  if (\"Unexpected response from Bitbucket server\".equals(e.getMessage())) {\n    // 2xx but non-JSON: check the logged body, likely SSO login page or proxy HTML\n  }\n}","preventionTips":["Verify REST calls return Content-Type application/json by testing with curl.","Configure SSO to bypass non-interactive clients or use a service account.","Ensure load balancers don't serve HTML maintenance pages with 200 status to API clients."],"tags":["java","bitbucket-server","json","response-validation"],"backgroundTag":"invalid-json-response","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}