Skip to content

SQL validator crashes on cached dev-mode error results missing runtime (Looker 26.14) #892

Description

@karow

Summary

Since a Looker instance update to 26.14.6, spectacles sql --branch ... (dev mode) crashes the entire run with:

Encountered an unexpected query result format. Unable to extract error details
from the Looker API's response. The unexpected response has been logged.
pydantic ValidationError: 2 validation errors for QueryResult
__root__ -> ErrorQueryResult -> data -> error    field required
__root__ -> ErrorQueryResult -> data -> runtime  field required

Cause

In dev mode, query results served from cache for queries touching derived tables with dev-mode filters (-- if dev -- conditional SQL) now come back with status: "error" carrying only the non-fatal warning note — and no runtime field:

{
  "status": "error",
  "result_source": "query",
  "data": {
    "from_cache": true,
    "id": "4bc672d22193f6a2dfe7304e82854c83",
    "errors": [
      {
        "message": "Note: This query contains derived tables with Development Mode filters. Query results in Production Mode might be different.",
        "message_details": null,
        "params": null,
        "edit_url": null,
        "error_pos": null,
        "fatal": false,
        "level": "error",
        "login_required_oauth_application_id": null
      }
    ],
    "data": []
  }
}

ErrorQueryResult.MultiErrorData declares runtime: float with no default, so parsing fails — one layer before get_valid_errors() would have excluded this exact note text (it's already in the WARNINGS tuple). The ErrorData variant doesn't match either (no error string).

Affected: 2.3.x and 2.4.x through v2.4.20 and current master (spectacles/models.pyMultiErrorData.runtime still required).

Suggested fix

One line — give the field a default so the cached-note payload parses, after which the existing warning exclusion handles it:

class MultiErrorData(BaseModel):
    id: str
    runtime: float = 0.0
    sql: Optional[str]
    errors: Optional[Tuple[QueryError, ...]]

Verified locally against spectacles 2.3.15 with the payload above: unpatched parse fails as in CI; with the default the payload parses, get_valid_errors() returns empty, and genuine SQL error payloads (which include runtime) still surface. Happy to open a PR.

Environment

  • spectacles 2.3.15 (also reproduced against 2.4.18/2.4.20 model definitions)
  • Looker 26.14.6, API 4.0
  • Command: spectacles sql --project <p> --branch <b> --remote-reset --ignore-hidden --fail-fast --concurrency 20

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions