BerriAI/litellm · error · DatabricksException

Unable to get json response

Error message

Unable to get json response - {e}, Original Response: {raw_response.text}

What it means

The Databricks chat completion handler wraps both raw_response.json() and construction of the DatabricksResponse pydantic model in one try/except. Any failure — a non-JSON body, or JSON missing required completion fields (id/created/usage) — raises DatabricksException 'Unable to get json response' embedding the parser error plus the entire original response text (request logging already ran with a redacted api_key). The 'Original Response' portion is your diagnosis.

Solutions

  1. Read 'Original Response' in the message — it shows exactly what came back (login HTML, error JSON, empty string)
  2. Verify the endpoint directly: curl <api_base>/<endpoint>/invocations with the same token
  3. Fix DATABRICKS_API_BASE so it targets the serving-endpoints API path, not the workspace UI
  4. If the body is valid JSON but lacks id/created/usage, the endpoint is not returning an OpenAI-compatible schema — use an OpenAI-compatible serving config or the right provider prefix
Defensive patterns

Strategy: try-catch

Validate before calling

import os

def databricks_base_ok() -> bool:
    base = os.getenv('DATABRICKS_API_BASE', '')
    return base.rstrip('/').endswith('/serving-endpoints')  # not the workspace UI

if not databricks_base_ok():
    raise RuntimeError('DATABRICKS_API_BASE must target the serving-endpoints API path')

Try / catch

try:
    resp = litellm.completion(model='databricks/my-ep', messages=msgs)
except Exception as e:
    if 'Unable to get json response' in str(e):
        log.error('non-OpenAI body from endpoint: %s', str(e)[-2000:])  # contains Original Response
    raise

Prevention

When it happens

Trigger: litellm.completion(model='databricks/...', ...) where the serving endpoint returns HTML (workspace login redirect when the URL points at the UI), an error JSON without completion fields, a 200 from a non-OpenAI-compatible gateway schema, or a truncated body from a dropped connection.

Common situations: DATABRICKS_API_BASE pointing at the workspace UI instead of the serving-endpoints path; endpoint in 'building/failed' state returning an error body; external-model endpoints with non-OpenAI response shapes; response-size limits at a proxy.

Understand the failure class

Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.

Related errors


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/3e15d4c1751ece37. Report an issue: GitHub.

Appendix: source

Thrown at litellm/llms/databricks/chat/transformation.py:626

        json_mode: bool | None = None,
    ) -> ModelResponse:
        # Redact sensitive data before logging to prevent credential leakage
        redacted_request_data: Final = self.redact_sensitive_data(request_data)

        ## LOGGING - Never log actual API keys
        logging_obj.post_call(
            input=messages,
            api_key="[REDACTED]",
            original_response=raw_response.text,
            additional_args={"complete_input_dict": redacted_request_data},
        )

        ## RESPONSE OBJECT
        try:
            completion_response: Final = DatabricksResponse(**raw_response.json())
        except Exception as e:
            response_headers: Final = getattr(raw_response, "headers", None)
            raise DatabricksException(
                message=f"Unable to get json response - {e}, Original Response: {raw_response.text}",
                status_code=raw_response.status_code,
                headers=response_headers,
            )

        _custom_llm_provider: Final = litellm_params.get("custom_llm_provider") or "databricks"
        _response_model: Final = completion_response.get("model") or ""
        model_response.model = f"{_custom_llm_provider}/{_response_model}"
        model_response.id = completion_response["id"]
        model_response.created = completion_response["created"]
        setattr(model_response, "usage", Usage(**completion_response["usage"]))

        model_response.choices = self._transform_dbrx_choices(
            choices=completion_response["choices"],
            json_mode=json_mode,
        )

        return model_response

View on GitHub (pinned to 77b7c6c40c)