RAPI Exceptions¶
Exceptions for the REST API client module: credential resolution, endpoint configuration, and HTTP requests.
Exception hierarchy¶
RapiError (base)
├── CredentialError # Credential resolution failed
├── EndpointNotFoundError # Endpoint not in config
├── EndpointAmbiguousError # Short reference matches multiple endpoints
├── RequestError # HTTP request failed
├── ResponseTooLargeError # Response exceeds max size
├── ConfirmationRequiredError # Dangerous endpoint called without confirmation
└── SafeguardMissingError # Dangerous method without safeguard in config
Common failure modes¶
CredentialErroris raised when credential resolution fails (missing environment variable, file not found, or SOPS decryption error).EndpointNotFoundErrorsurfaces when the requested endpoint reference doesn’t match any configured endpoint.EndpointAmbiguousErrorindicates a short reference (e.g.,"users") matches endpoints in multiple APIs.RequestErrorwraps HTTP failures including timeouts and 5xx errors after retry exhaustion.ResponseTooLargeErrorindicates the response body exceeds the configuredmax_response_sizelimit.ConfirmationRequiredErroris raised at runtime when calling a dangerous endpoint (DELETE, PUT) without the requiredconfirmparameter.SafeguardMissingErroris raised at config load time when an endpoint uses a dangerous method but lacks asafeguardstring.
Usage patterns¶
Handling credential errors¶
from kstlib.rapi import RapiClient
from kstlib.rapi.exceptions import CredentialError
try:
client = RapiClient()
response = client.call("secure_api.endpoint")
except CredentialError as e:
logger.error(f"Credential resolution failed: {e}")
logger.error(f"Credential name: {e.credential_name}")
# Check environment variable or credential file
Handling endpoint resolution¶
from kstlib.rapi import RapiClient
from kstlib.rapi.exceptions import EndpointNotFoundError, EndpointAmbiguousError
client = RapiClient()
try:
response = client.call("users") # Short reference
except EndpointAmbiguousError as e:
# Multiple APIs have "users" endpoint
logger.warning(f"Ambiguous: {e.matching_apis}")
# Use full reference instead
response = client.call("github.users")
except EndpointNotFoundError as e:
logger.error(f"Endpoint not found: {e.endpoint_ref}")
logger.error(f"Searched APIs: {e.searched_apis}")
Request error handling¶
from kstlib.rapi import RapiClient
from kstlib.rapi.exceptions import RequestError
client = RapiClient()
try:
response = client.call("httpbin.delay", 60) # May timeout
except RequestError as e:
logger.error(f"Request failed: {e}")
if e.retryable:
logger.info("Error is retryable, consider retry later")
if e.status_code:
logger.info(f"HTTP status: {e.status_code}")
Response size validation¶
from kstlib.rapi import RapiClient
from kstlib.rapi.exceptions import ResponseTooLargeError
client = RapiClient()
try:
response = client.call("api.large_endpoint")
except ResponseTooLargeError as e:
logger.warning(f"Response too large: {e.size} bytes")
logger.warning(f"Max allowed: {e.max_size} bytes")
# Consider pagination or streaming
Safeguard confirmation¶
from kstlib.rapi import RapiClient
from kstlib.rapi.exceptions import ConfirmationRequiredError
client = RapiClient()
try:
# Dangerous endpoint without confirmation
client.call("admin.delete-user", user_id="123")
except ConfirmationRequiredError as e:
logger.warning(f"Confirmation required: {e.expected}")
# Ask user for confirmation, then retry
if user_confirms():
client.call("admin.delete-user", user_id="123", confirm=e.expected)
Safe wrapper pattern¶
from kstlib.rapi import RapiClient
from kstlib.rapi.exceptions import RapiError
def safe_api_call(endpoint: str, *args, **kwargs) -> dict | None:
"""Make API call with comprehensive error handling."""
client = RapiClient()
try:
response = client.call(endpoint, *args, **kwargs)
if response.ok:
return response.data
logger.warning(f"API returned {response.status_code}")
return None
except RapiError as e:
logger.error(f"API call failed: {e}")
return None
API reference¶
Exceptions for the RAPI module.
This module defines the exception hierarchy for REST API operations.
- exception kstlib.rapi.exceptions.ConfirmationRequiredError(endpoint_ref, *, expected, actual=None)[source]
Bases:
RapiErrorRaised when a dangerous endpoint requires confirmation.
This exception is raised at runtime when calling an endpoint that has a safeguard configured but the confirm parameter is missing or incorrect.
- endpoint_ref
Full endpoint reference (api.endpoint).
- expected
Expected confirmation string.
- actual
Actual confirmation string provided (None if missing).
Examples
>>> raise ConfirmationRequiredError("api.delete", expected="DELETE X") Traceback (most recent call last): ... kstlib.rapi.exceptions.ConfirmationRequiredError: ... requires confirmation...
- __init__(self, endpoint_ref: 'str', *, expected: 'str', actual: 'str | None' = None) 'None' -> None[source]
Initialize ConfirmationRequiredError.
- exception kstlib.rapi.exceptions.CredentialError(credential_name, reason)[source]
Bases:
RapiErrorRaised when credential resolution fails.
- credential_name
Name of the credential that failed.
- reason
Reason for the failure.
Examples
>>> raise CredentialError("github", "Environment variable not set") Traceback (most recent call last): ... kstlib.rapi.exceptions.CredentialError: Credential 'github' failed: Environment variable not set
- exception kstlib.rapi.exceptions.EndpointAmbiguousError(endpoint_name, matching_apis)[source]
Bases:
RapiErrorRaised when an endpoint name matches multiple APIs.
- endpoint_name
The ambiguous endpoint name.
- matching_apis
List of API names containing this endpoint.
Examples
>>> raise EndpointAmbiguousError("get_data", ["api1", "api2"]) Traceback (most recent call last): ... kstlib.rapi.exceptions.EndpointAmbiguousError: Endpoint 'get_data' is ambiguous, found in: api1, api2
- exception kstlib.rapi.exceptions.EndpointCollisionError(endpoint_ref, source_files)[source]
Bases:
RapiErrorRaised when endpoints collide in strict mode.
This exception is raised at config load time when the same endpoint reference is defined in multiple files and strict mode is enabled.
- endpoint_ref
Full endpoint reference (api.endpoint).
- source_files
List of files defining this endpoint.
Examples
>>> raise EndpointCollisionError("api.create", ["a.rapi.yml", "b.rapi.yml"]) Traceback (most recent call last): ... kstlib.rapi.exceptions.EndpointCollisionError: Endpoint 'api.create' defined in multiple files...
- exception kstlib.rapi.exceptions.EndpointNotFoundError(endpoint_ref, searched_apis=None)[source]
Bases:
RapiErrorRaised when an endpoint cannot be resolved.
- endpoint_ref
The endpoint reference that was not found.
- searched_apis
List of API names that were searched.
Examples
>>> raise EndpointNotFoundError("unknown.endpoint") Traceback (most recent call last): ... kstlib.rapi.exceptions.EndpointNotFoundError: Endpoint 'unknown.endpoint' not found
- exception kstlib.rapi.exceptions.EnvVarError(var_name, source=None)[source]
Bases:
RapiErrorRaised when environment variable substitution fails.
This exception is raised at config load time when a required environment variable is not set and no default value is provided.
- var_name
Name of the missing environment variable.
- source
Source file or context where the variable was referenced.
Examples
>>> raise EnvVarError("VIYA_HOST") Traceback (most recent call last): ... kstlib.rapi.exceptions.EnvVarError: Environment variable 'VIYA_HOST' is not set...
- exception kstlib.rapi.exceptions.MinifyRequiresRawError(message=None)[source]
Bases:
RapiErrorRaised when
--minify(compact JSON) is requested without--raw.Rich console rendering reformats output regardless of compact JSON flags, so
--minifywithout--rawis silently ineffective. Surface the constraint at flag-validation time with a hint pointing to--raw --minify.The kstlib CLI raises
typer.BadParameterdirectly for native Typer error formatting. This exception is exported for callers that need to surface the same constraint programmatically (for example, future pipeline steps exposing equivalentminifyandoutsemantics).- message
Human-readable error message containing the hint.
Examples
>>> error = MinifyRequiresRawError() >>> "--raw --minify" in str(error) True >>> isinstance(error, RapiError) True
- DEFAULT_MESSAGE = '--minify requires --raw (Rich rendering ignores compact JSON formatting). Hint: use --raw --minify.'
- exception kstlib.rapi.exceptions.RapiError(message, *, details=None)[source]
Bases:
KstlibErrorBase exception for all RAPI errors.
- message
Human-readable error message.
- details
Additional error context as key-value pairs.
Examples
>>> raise RapiError("Something went wrong", details={"endpoint": "test"}) Traceback (most recent call last): ... kstlib.rapi.exceptions.RapiError: Something went wrong
- exception kstlib.rapi.exceptions.RequestError(message, *, status_code=None, response_body=None, retryable=False)[source]
Bases:
RapiErrorRaised when an HTTP request fails.
- status_code
HTTP status code (if available).
- response_body
Response body (if available).
- retryable
Whether the error is potentially retryable.
Examples
>>> raise RequestError("Server error", status_code=500, retryable=True) Traceback (most recent call last): ... kstlib.rapi.exceptions.RequestError: Server error
- __init__(self, message: 'str', *, status_code: 'int | None' = None, response_body: 'str | None' = None, retryable: 'bool' = False) 'None' -> None[source]
Initialize RequestError.
- exception kstlib.rapi.exceptions.ResponseTooLargeError(response_size, max_size)[source]
Bases:
RapiErrorRaised when response exceeds max_response_size limit.
- response_size
Actual response size in bytes.
- max_size
Maximum allowed size in bytes.
Examples
>>> raise ResponseTooLargeError(15_000_000, 10_000_000) Traceback (most recent call last): ... kstlib.rapi.exceptions.ResponseTooLargeError: Response size 15000000 exceeds limit 10000000
- exception kstlib.rapi.exceptions.SafeguardMissingError(endpoint_ref, method)[source]
Bases:
RapiErrorRaised when endpoint requires safeguard but none is configured.
This exception is raised at config load time when an endpoint uses a method that requires a safeguard (e.g., DELETE, PUT) but no safeguard string is provided in the endpoint configuration.
- endpoint_ref
Full endpoint reference (api.endpoint).
- method
HTTP method that requires the safeguard.
Examples
>>> raise SafeguardMissingError("api.delete", "DELETE") Traceback (most recent call last): ... kstlib.rapi.exceptions.SafeguardMissingError: ... requires a safeguard...
- exception kstlib.rapi.exceptions.ServerNotFoundError(server_name, available=None)[source]
Bases:
RapiErrorRaised when a named server profile does not exist.
- server_name
The server name that was not found.
- available
List of available server names.
Examples
>>> raise ServerNotFoundError("staging", available=["source", "target"]) Traceback (most recent call last): ... kstlib.rapi.exceptions.ServerNotFoundError: Server profile 'staging' not found...