Versatile Data Kit SDK plugin exposing CLI commands for managing the lifecycle of a Data Jobs.
Specialized error handling decorator for Control Service API calls that provides user-friendly error messages, proper error categorization, and actionable guidance for error resolution. The decorator transforms low-level API exceptions into structured VDK errors with appropriate context and remediation steps.
from taurus_datajob_api import ApiExceptionDecorator class that wraps Control Service API calls with comprehensive error handling and user-friendly error messages.
class ConstrolServiceApiErrorDecorator:
def __init__(self, what="Control Service Error", consequences="Operation cannot complete."):
"""
Initialize error decorator with default error messages.
Parameters:
- what: str - Default error description (what went wrong)
- consequences: str - Default consequences description (impact on user)
"""
def __call__(self, fn):
"""
Decorator function that wraps API calls with error handling.
Parameters:
- fn: function - The function to wrap with error handling
Returns:
function: Decorated function with error handling
The decorator catches ApiException and other exceptions,
transforms them into appropriate VDK error types:
- VdkConfigurationError: For 401 authentication errors
- UserCodeError: For 400-499 client errors
- PlatformServiceError: For 500+ server errors and other exceptions
"""Internal method that processes API exceptions and creates structured error information.
def _get_error(self, exception: ApiException):
"""
Extract and format error information from API exceptions.
Parameters:
- exception: ApiException - The API exception to process
Returns:
dict: Structured error information with what, why, consequences, countermeasures
Handles different HTTP status codes:
- 401: Authentication/authorization errors
- 404: Resource not found errors
- 400-499: Other client errors
- 500+: Server errors
Attempts to parse JSON error responses, falls back to generic templates.
"""Handles authentication and authorization failures with specific guidance.
# Error structure for 401 responses
{
"what": "Control Service Error",
"why": "The request has not been applied because it lacks valid authentication credentials",
"consequences": "Operation cannot complete",
"countermeasures": [
"Try to login again using VDK CLI login command",
"Set correct api token configuration",
"Make sure you have permission to execute the given operation",
"Investigate the error returned by control service",
"Contact support team if all else fails"
]
}Handles cases where requested resources (data jobs, teams, etc.) don't exist.
# Error structure for 404 responses
{
"what": "Control Service Error",
"why": "The requested resource cannot be found. You may have a spelling mistake or the data job has not been created",
"consequences": "Operation cannot complete",
"countermeasures": [
"Make sure that the data job name and team name are spelled correctly (case-sensitive)",
"Make sure you have run `vdk create --cloud` before doing this operation on a data job"
]
}Handles client-side errors like bad requests, validation failures, etc.
# Error structure for other 4xx responses
{
"what": "Control Service Error",
"why": "Http error: status: {status} - {body}",
"consequences": "Operation cannot complete",
"countermeasures": "See error and try to resolve it or open ticket to SRE team"
}Handles server-side errors and platform issues.
# Error structure for 5xx responses
{
"what": "Control Service Error",
"why": "Http error: status: {status} - {body}",
"consequences": "Operation cannot complete",
"countermeasures": "See error and try to resolve it or open ticket to SRE team"
}The decorator is applied to API client methods to provide consistent error handling:
from vdk.plugin.control_cli_plugin.control_service_api_error_decorator import (
ConstrolServiceApiErrorDecorator
)
class MyApiClient:
@ConstrolServiceApiErrorDecorator()
def read_data(self, job_name: str, team_name: str):
# API call that may raise ApiException
return self.api.get_data(job_name=job_name, team_name=team_name)
@ConstrolServiceApiErrorDecorator(
what="Data Write Error",
consequences="Data was not saved to Control Service"
)
def write_data(self, job_name: str, team_name: str, data: dict):
# API call with custom error messages
return self.api.put_data(job_name=job_name, team_name=team_name, data=data)Customize error messages for specific operations:
# Custom error decorator for properties operations
@ConstrolServiceApiErrorDecorator(
what="Properties Read Error",
consequences="Job properties could not be retrieved"
)
def read_properties(self, job_name: str, team_name: str):
return self.api.data_job_properties_read(
team_name=team_name,
job_name=job_name,
deployment_id="TODO"
)Client code receives structured VDK errors instead of raw API exceptions:
from vdk.internal.core.errors import VdkConfigurationError, UserCodeError, PlatformServiceError
try:
properties = client.read_properties("my-job", "my-team")
except VdkConfigurationError as e:
# Authentication/configuration issue
print(f"Configuration error: {e}")
print("Please run 'vdk login' to authenticate")
except UserCodeError as e:
# Client error (bad request, not found, etc.)
print(f"Request error: {e}")
print("Check job name and team name spelling")
except PlatformServiceError as e:
# Server error or other platform issue
print(f"Platform error: {e}")
print("Try again later or contact support")The decorator attempts to parse JSON error responses from the Control Service:
# Example JSON error response from Control Service
{
"what": "Data Job Not Found",
"why": "No data job found with name 'my-job' for team 'my-team'",
"consequences": "Cannot retrieve job properties",
"countermeasures": "Verify job name and team, or create the job first"
}If JSON parsing fails, the decorator falls back to generic error templates:
try:
error = json.loads(exception.body)
except Exception:
# Fallback to generic error structure based on HTTP status
if exception.status == 401:
error = create_auth_error_template()
elif exception.status == 404:
error = create_not_found_error_template()
else:
error = create_generic_error_template()class ControlServicePropertiesServiceClient:
@ConstrolServiceApiErrorDecorator()
def read_properties(self, job_name: str, team_name: str):
# Automatically handles authentication, not found, and server errors
return self.api.data_job_properties_read(
team_name=team_name,
job_name=job_name,
deployment_id="TODO"
)class ControlServiceSecretsServiceClient:
@ConstrolServiceApiErrorDecorator()
def write_secrets(self, job_name: str, team_name: str, secrets: Dict):
# Error handling preserves security - no secret values in error messages
return self.api.data_job_secrets_update(
team_name=team_name,
job_name=job_name,
deployment_id="TODO",
request_body=secrets
)All structured errors follow the VDK error standard format:
{
"what": "Brief description of what went wrong",
"why": "Detailed explanation of the root cause",
"consequences": "Impact on the user and their operation",
"countermeasures": "Actionable steps to resolve the issue"
}This structure enables:
Install with Tessl CLI
npx tessl i tessl/pypi-vdk-plugin-control-cli