Custom Exception Systemο
Structured error handling with error codes, details, and cause chaining. All exceptions extend PlatformError.
Hierarchyο
PlatformError (base)
βββ PlatformConfigurationError (invalid/missing config)
βββ PlatformNotFoundError (resource not found)
β βββ WorkspaceNotFoundError
β βββ DeploymentNotFoundError
β βββ ConfigurationNotFoundError
β βββ ProviderNotFoundError
β βββ ResourceTypeNotFoundError
β βββ PlatformFileNotFoundError (file not found)
βββ PlatformValidationError (validation failures)
β βββ ModelValidationError (Pydantic model validation)
β βββ InvalidReferenceError (invalid cross-references)
β βββ UnsupportedKindError (unsupported resource kind)
β βββ PathValidationError (CLI/workspace path errors)
βββ PlatformStateError (service state issues)
β βββ ServiceNotValidatedError (method called before validate())
βββ ServiceNotAvailableError (required service unavailable)
βββ ServiceLoadError (failed to load related services)
Base Exception Featuresο
PlatformError - All exceptions inherit:
error_code: Machine-readable identifier (e.g.,"FILE_NOT_FOUND")details: Dict with contextual informationcause: Original exception for chainingto_dict(): Convert to structured dict for logging/API
from strata.exceptions import PlatformError
try:
# operation
except Exception as e:
raise PlatformError(
message="Operation failed",
error_code="OPERATION_FAILED",
details={"operation": "load_data", "path": "/some/path"},
cause=e
)
Common Usageο
Configuration errors:
from strata.exceptions import PlatformConfigurationError
if not path and not data:
raise PlatformConfigurationError("Either path or data must be provided")
Model validation:
from strata.exceptions import ModelValidationError
try:
model = MyModel.model_validate(data)
except ValidationError as e:
raise ModelValidationError(
model_name="MyModel",
validation_errors=e.errors(),
) from e
Service state:
from strata.exceptions import ServiceNotValidatedError
def _ensure_validated(self):
if not self._validated:
raise ServiceNotValidatedError(self.__class__.__name__)
Invalid references:
from strata.exceptions import InvalidReferenceError
raise InvalidReferenceError(
source_type="Topology",
source_name=name,
reference_type="provider",
reference_value=provider,
)
Service Error Handling Patternο
def validate(self):
"""Validate with structured error storage."""
try:
self.model = ModelClass.model_validate(self.data)
self._validated = True
return True, []
except ValidationError as e:
err = ModelValidationError(
model_name=ModelClass.__name__,
validation_errors=e.errors(),
)
self._errors.append(err.message)
return False, self._errors
Accessing Errorsο
String errors (backward compatible):
service = DeploymentService(data=data)
is_valid, errors = service.validate()
if not is_valid:
for error in service.get_validation_errors():
print(f"Error: {error}")
Structured errors (programmatic):
if not is_valid:
for error in service.get_structured_errors():
print(f"Code: {error.error_code}")
print(f"Details: {error.details}")
error_dict = error.to_dict() # For API response
Testingο
import pytest
from strata.exceptions import (
PlatformConfigurationError,
ServiceNotValidatedError,
PlatformFileNotFoundError,
)
def test_initialization_error():
with pytest.raises(PlatformConfigurationError, match="Either path or data"):
MyService()
def test_validation_required():
service = MyService(data=valid_data)
with pytest.raises(ServiceNotValidatedError, match="must be validated"):
service.get_kind()
def test_file_not_found():
err = PlatformFileNotFoundError("/some/file.yaml", file_type="Configuration")
assert err.error_code == "FILE_NOT_FOUND"
assert err.details["path"] == "/some/file.yaml"
Best Practicesο
Use specific exceptions: Choose most specific class, create new types if needed
Provide context: Use
detailsdict with relevant info (names, paths, options)Chain exceptions: Use
causeparameter for debuggingStore structured: Add to
_structured_errors+ string to_validation_errors