Skip to content

Exceptions

Every error the SDK raises descends from VulnersError. See Error model for how a response is classified into one of these.

VulnersError
├── APIError                         # a request failed
│   ├── APIConnectionError           # no response (DNS/connect/read)
│   │   └── APITimeoutError          # timed out
│   ├── APIResponseValidationError   # 2xx body didn't match the schema
│   └── APIStatusError               # non-success status (or a 200 error envelope)
│       ├── BadRequestError          # 400
│       ├── AuthenticationError      # 401
│       ├── PermissionDeniedError    # 403
│       ├── NotFoundError            # 404
│       ├── ConflictError            # 409
│       ├── UnprocessableEntityError # 422
│       ├── RateLimitError           # 429  (inspect .retry_after)
│       └── InternalServerError      # 5xx
└── SearchWindowExceeded             # offset + limit > 10000  (also a ValueError)

vulners.VulnersError

Bases: Exception

Root of every error the SDK raises.

vulners.APIError

APIError(message: str | None = None, *, status_code: int | None = None, error_code: int | str | None = None, data: Any = None, retry_after: float | None = None, request_id: str | None = None, validation_errors: list[dict[str, Any]] | None = None)

Bases: VulnersError, VulnersApiError

The server reported a failure.

Carries what the pipeline could recover about the failure. status_code is the HTTP status (None only in synthetic cases); error_code is the Vulners errorCode when the body carried one; data is the full, secret-redacted error payload; retry_after is the parsed Retry-After hint; request_id is the server request correlation id when a response header carried one; validation_errors holds the structured items of a v4 validation failure (each without the input echo).

Also inherits the legacy :class:~vulners.base.VulnersApiError, so v3-era except VulnersApiError handlers catch v4 server errors during migration (the legacy class itself is untouched). http_status and body are the v3-compatible spellings of status_code and data.

Source code in src/vulners/_exceptions.py
def __init__(
    self,
    message: str | None = None,
    *,
    status_code: int | None = None,
    error_code: int | str | None = None,
    data: Any = None,
    retry_after: float | None = None,
    request_id: str | None = None,
    validation_errors: list[dict[str, Any]] | None = None,
) -> None:
    self.status_code = status_code
    self.error_code = error_code
    self.message = message
    self.data = data
    self.retry_after = retry_after
    self.request_id = request_id
    self.validation_errors = validation_errors or []
    # Direct Exception.__init__: the legacy VulnersApiError.__init__ in the
    # MRO has an incompatible (http_status, data) signature and must not run.
    Exception.__init__(self, message if message is not None else data)

http_status property

http_status: int | None

v3-compatible alias of :attr:status_code.

body property

body: Any

Alias of :attr:data (the redacted error payload).

vulners.APIStatusError

APIStatusError(message: str | None = None, *, status_code: int | None = None, error_code: int | str | None = None, data: Any = None, retry_after: float | None = None, request_id: str | None = None, validation_errors: list[dict[str, Any]] | None = None)

Bases: APIError

A non-success HTTP status (or a 200 carrying an error envelope).

status_code is always populated for this branch (never None).

Source code in src/vulners/_exceptions.py
def __init__(
    self,
    message: str | None = None,
    *,
    status_code: int | None = None,
    error_code: int | str | None = None,
    data: Any = None,
    retry_after: float | None = None,
    request_id: str | None = None,
    validation_errors: list[dict[str, Any]] | None = None,
) -> None:
    self.status_code = status_code
    self.error_code = error_code
    self.message = message
    self.data = data
    self.retry_after = retry_after
    self.request_id = request_id
    self.validation_errors = validation_errors or []
    # Direct Exception.__init__: the legacy VulnersApiError.__init__ in the
    # MRO has an incompatible (http_status, data) signature and must not run.
    Exception.__init__(self, message if message is not None else data)

vulners.APIConnectionError

APIConnectionError(message: str = 'Connection error.', *, data: Any = None)

Bases: VulnersError

The request never got a response (DNS/connect/read failure).

A sibling of :class:APIError, not a subclass: no server was heard from, so there is no status/errorCode surface — and legacy except VulnersApiError deliberately does not match (v3 surfaced these as raw httpx errors too).

Source code in src/vulners/_exceptions.py
def __init__(self, message: str = "Connection error.", *, data: Any = None) -> None:
    self.message = message
    self.data = data
    super().__init__(message)

vulners.APITimeoutError

APITimeoutError(message: str = 'Request timed out.')

Bases: APIConnectionError

The request timed out before a response was received.

Source code in src/vulners/_exceptions.py
def __init__(self, message: str = "Request timed out.") -> None:
    super().__init__(message)

vulners.APIResponseValidationError

APIResponseValidationError(message: str, *, status_code: int | None = None, data: Any = None)

Bases: VulnersError

A 2xx response body did not match what the endpoint promised.

A sibling of :class:APIError: the server did not report an error — the response shape itself is what failed. status_code is informational (the 2xx status the malformed body arrived with).

Source code in src/vulners/_exceptions.py
def __init__(self, message: str, *, status_code: int | None = None, data: Any = None) -> None:
    self.message = message
    self.status_code = status_code
    self.data = data
    super().__init__(message)

vulners.BadRequestError

BadRequestError(message: str | None = None, *, status_code: int | None = None, error_code: int | str | None = None, data: Any = None, retry_after: float | None = None, request_id: str | None = None, validation_errors: list[dict[str, Any]] | None = None)

Bases: APIStatusError

400 (or a v3 bad-parameter error).

Source code in src/vulners/_exceptions.py
def __init__(
    self,
    message: str | None = None,
    *,
    status_code: int | None = None,
    error_code: int | str | None = None,
    data: Any = None,
    retry_after: float | None = None,
    request_id: str | None = None,
    validation_errors: list[dict[str, Any]] | None = None,
) -> None:
    self.status_code = status_code
    self.error_code = error_code
    self.message = message
    self.data = data
    self.retry_after = retry_after
    self.request_id = request_id
    self.validation_errors = validation_errors or []
    # Direct Exception.__init__: the legacy VulnersApiError.__init__ in the
    # MRO has an incompatible (http_status, data) signature and must not run.
    Exception.__init__(self, message if message is not None else data)

vulners.AuthenticationError

AuthenticationError(message: str | None = None, *, status_code: int | None = None, error_code: int | str | None = None, data: Any = None, retry_after: float | None = None, request_id: str | None = None, validation_errors: list[dict[str, Any]] | None = None)

Bases: APIStatusError

401 — the API key is missing or invalid.

Source code in src/vulners/_exceptions.py
def __init__(
    self,
    message: str | None = None,
    *,
    status_code: int | None = None,
    error_code: int | str | None = None,
    data: Any = None,
    retry_after: float | None = None,
    request_id: str | None = None,
    validation_errors: list[dict[str, Any]] | None = None,
) -> None:
    self.status_code = status_code
    self.error_code = error_code
    self.message = message
    self.data = data
    self.retry_after = retry_after
    self.request_id = request_id
    self.validation_errors = validation_errors or []
    # Direct Exception.__init__: the legacy VulnersApiError.__init__ in the
    # MRO has an incompatible (http_status, data) signature and must not run.
    Exception.__init__(self, message if message is not None else data)

vulners.PermissionDeniedError

PermissionDeniedError(message: str | None = None, *, status_code: int | None = None, error_code: int | str | None = None, data: Any = None, retry_after: float | None = None, request_id: str | None = None, validation_errors: list[dict[str, Any]] | None = None)

Bases: APIStatusError

403 — the key is valid but not permitted (or blocked upstream).

Source code in src/vulners/_exceptions.py
def __init__(
    self,
    message: str | None = None,
    *,
    status_code: int | None = None,
    error_code: int | str | None = None,
    data: Any = None,
    retry_after: float | None = None,
    request_id: str | None = None,
    validation_errors: list[dict[str, Any]] | None = None,
) -> None:
    self.status_code = status_code
    self.error_code = error_code
    self.message = message
    self.data = data
    self.retry_after = retry_after
    self.request_id = request_id
    self.validation_errors = validation_errors or []
    # Direct Exception.__init__: the legacy VulnersApiError.__init__ in the
    # MRO has an incompatible (http_status, data) signature and must not run.
    Exception.__init__(self, message if message is not None else data)

vulners.NotFoundError

NotFoundError(message: str | None = None, *, status_code: int | None = None, error_code: int | str | None = None, data: Any = None, retry_after: float | None = None, request_id: str | None = None, validation_errors: list[dict[str, Any]] | None = None)

Bases: APIStatusError

404 — the resource does not exist.

Source code in src/vulners/_exceptions.py
def __init__(
    self,
    message: str | None = None,
    *,
    status_code: int | None = None,
    error_code: int | str | None = None,
    data: Any = None,
    retry_after: float | None = None,
    request_id: str | None = None,
    validation_errors: list[dict[str, Any]] | None = None,
) -> None:
    self.status_code = status_code
    self.error_code = error_code
    self.message = message
    self.data = data
    self.retry_after = retry_after
    self.request_id = request_id
    self.validation_errors = validation_errors or []
    # Direct Exception.__init__: the legacy VulnersApiError.__init__ in the
    # MRO has an incompatible (http_status, data) signature and must not run.
    Exception.__init__(self, message if message is not None else data)

vulners.ConflictError

ConflictError(message: str | None = None, *, status_code: int | None = None, error_code: int | str | None = None, data: Any = None, retry_after: float | None = None, request_id: str | None = None, validation_errors: list[dict[str, Any]] | None = None)

Bases: APIStatusError

409 — the request conflicts with the current server state.

Source code in src/vulners/_exceptions.py
def __init__(
    self,
    message: str | None = None,
    *,
    status_code: int | None = None,
    error_code: int | str | None = None,
    data: Any = None,
    retry_after: float | None = None,
    request_id: str | None = None,
    validation_errors: list[dict[str, Any]] | None = None,
) -> None:
    self.status_code = status_code
    self.error_code = error_code
    self.message = message
    self.data = data
    self.retry_after = retry_after
    self.request_id = request_id
    self.validation_errors = validation_errors or []
    # Direct Exception.__init__: the legacy VulnersApiError.__init__ in the
    # MRO has an incompatible (http_status, data) signature and must not run.
    Exception.__init__(self, message if message is not None else data)

vulners.UnprocessableEntityError

UnprocessableEntityError(message: str | None = None, *, status_code: int | None = None, error_code: int | str | None = None, data: Any = None, retry_after: float | None = None, request_id: str | None = None, validation_errors: list[dict[str, Any]] | None = None)

Bases: APIStatusError

422 — request validation failed.

Source code in src/vulners/_exceptions.py
def __init__(
    self,
    message: str | None = None,
    *,
    status_code: int | None = None,
    error_code: int | str | None = None,
    data: Any = None,
    retry_after: float | None = None,
    request_id: str | None = None,
    validation_errors: list[dict[str, Any]] | None = None,
) -> None:
    self.status_code = status_code
    self.error_code = error_code
    self.message = message
    self.data = data
    self.retry_after = retry_after
    self.request_id = request_id
    self.validation_errors = validation_errors or []
    # Direct Exception.__init__: the legacy VulnersApiError.__init__ in the
    # MRO has an incompatible (http_status, data) signature and must not run.
    Exception.__init__(self, message if message is not None else data)

vulners.RateLimitError

RateLimitError(message: str | None = None, *, status_code: int | None = None, error_code: int | str | None = None, data: Any = None, retry_after: float | None = None, request_id: str | None = None, validation_errors: list[dict[str, Any]] | None = None)

Bases: APIStatusError

429 — too many requests; inspect retry_after.

Source code in src/vulners/_exceptions.py
def __init__(
    self,
    message: str | None = None,
    *,
    status_code: int | None = None,
    error_code: int | str | None = None,
    data: Any = None,
    retry_after: float | None = None,
    request_id: str | None = None,
    validation_errors: list[dict[str, Any]] | None = None,
) -> None:
    self.status_code = status_code
    self.error_code = error_code
    self.message = message
    self.data = data
    self.retry_after = retry_after
    self.request_id = request_id
    self.validation_errors = validation_errors or []
    # Direct Exception.__init__: the legacy VulnersApiError.__init__ in the
    # MRO has an incompatible (http_status, data) signature and must not run.
    Exception.__init__(self, message if message is not None else data)

vulners.InternalServerError

InternalServerError(message: str | None = None, *, status_code: int | None = None, error_code: int | str | None = None, data: Any = None, retry_after: float | None = None, request_id: str | None = None, validation_errors: list[dict[str, Any]] | None = None)

Bases: APIStatusError

5xx — the server failed to handle the request.

Source code in src/vulners/_exceptions.py
def __init__(
    self,
    message: str | None = None,
    *,
    status_code: int | None = None,
    error_code: int | str | None = None,
    data: Any = None,
    retry_after: float | None = None,
    request_id: str | None = None,
    validation_errors: list[dict[str, Any]] | None = None,
) -> None:
    self.status_code = status_code
    self.error_code = error_code
    self.message = message
    self.data = data
    self.retry_after = retry_after
    self.request_id = request_id
    self.validation_errors = validation_errors or []
    # Direct Exception.__init__: the legacy VulnersApiError.__init__ in the
    # MRO has an incompatible (http_status, data) signature and must not run.
    Exception.__init__(self, message if message is not None else data)

vulners.SearchWindowExceeded

Bases: VulnersError, ValueError

The search page window (offset + limit > 10000) was exceeded.

Derives from :class:ValueError too, so existing except ValueError handlers around pagination keep matching.