Skip to content

Error Handling

All ContextUnity services use a unified exception hierarchy rooted in ContextUnityError. This ensures consistent error codes, gRPC status mapping, and protocol-level error propagation across the service mesh.

Exception Hierarchy

Exception
└── ContextUnityError (INTERNAL_ERROR)
├── ConfigurationError (CONFIGURATION_ERROR)
│ ├── RedisNotAvailable (REDIS_NOT_AVAILABLE)
│ └── ServiceStartupError (SERVICE_STARTUP_ERROR)
├── RetrievalError (RETRIEVAL_ERROR)
├── IntentDetectionError (INTENT_ERROR)
├── ProviderError (PROVIDER_ERROR)
│ └── StorageError (STORAGE_ERROR)
│ ├── DatabaseConnectionError (DB_CONNECTION_ERROR)
│ └── RedisConnectionError (REDIS_CONNECTION_ERROR)
├── SecurityError (SECURITY_ERROR)
│ └── TamperDetectedError (TAMPER_DETECTED)
├── ConnectorError (CONNECTOR_ERROR)
├── ModelError (MODEL_ERROR)
├── IngestionError (INGESTION_ERROR)
├── GraphBuilderError (GRAPH_BUILDER_ERROR)
├── TransformerError (TRANSFORMER_ERROR)
├── LLMExecutionError (LLM_EXECUTION_ERROR)
├── FederatedToolTimeout (FEDERATED_TIMEOUT)
└── PlatformServiceError (PLATFORM_SERVICE_ERROR)

Usage

from contextunity.core.exceptions import (
ContextUnityError,
ConfigurationError,
SecurityError,
)
# Raise with default message
raise ConfigurationError()
# Raise with custom message + extra details
raise SecurityError(
message="Token expired for tenant",
tenant_id="my_app",
expired_at="2026-01-01T00:00:00Z",
)

Every exception carries:

  • code — stable error code string (e.g. "SECURITY_ERROR")
  • message — human-readable description
  • details — arbitrary keyword context dictionary

Error Codes Reference

ExceptionCodeDescription
ContextUnityErrorINTERNAL_ERRORBase — uncategorized platform error
ConfigurationErrorCONFIGURATION_ERRORInvalid or missing configuration
RetrievalErrorRETRIEVAL_ERRORRetrieval pipeline failure
IntentDetectionErrorINTENT_ERRORIntent classification failure
ProviderErrorPROVIDER_ERRORStorage/provider layer failure
SecurityErrorSECURITY_ERRORToken missing, invalid, or expired
TamperDetectedErrorTAMPER_DETECTEDPrompt HMAC signature mismatch
ConnectorErrorCONNECTOR_ERRORData connector failure
ModelErrorMODEL_ERRORLLM or embedding model failure
IngestionErrorINGESTION_ERRORIngestion pipeline failure
GraphBuilderErrorGRAPH_BUILDER_ERRORGraph compilation failure
TransformerErrorTRANSFORMER_ERRORData transformation failure
StorageErrorSTORAGE_ERRORDatabase or storage operation failure
DatabaseConnectionErrorDB_CONNECTION_ERRORDatabase connection failure
LLMExecutionErrorLLM_EXECUTION_ERRORModel unavailable, rate-limited, or malformed response
FederatedToolTimeoutFEDERATED_TIMEOUTFederated tool did not respond within deadline
PlatformServiceErrorPLATFORM_SERVICE_ERRORCross-service call failure (Brain/Shield/Worker)
RedisNotAvailableREDIS_NOT_AVAILABLERedis package not installed (gracefully degraded)
RedisConnectionErrorREDIS_CONNECTION_ERRORRedis server unreachable (includes TLS hint)
ServiceStartupErrorSERVICE_STARTUP_ERRORService failed to start during platform bootstrap

gRPC Error Mapping

The @grpc_error_handler decorator automatically maps ContextUnityError to appropriate gRPC status codes:

from contextunity.core.grpc_errors import grpc_error_handler
class BrainService(brain_pb2_grpc.BrainServiceServicer):
@grpc_error_handler
async def Search(self, request, context):
# If SecurityError is raised → grpc.StatusCode.PERMISSION_DENIED
# If StorageError is raised → grpc.StatusCode.UNAVAILABLE
...
Error CodegRPC Status
SECURITY_ERRORPERMISSION_DENIED
TAMPER_DETECTEDABORTED
CONFIGURATION_ERRORFAILED_PRECONDITION
RETRIEVAL_ERRORNOT_FOUND
PROVIDER_ERROR, STORAGE_ERROR, DB_CONNECTION_ERROR, CONNECTOR_ERRORUNAVAILABLE
MODEL_ERROR, GRAPH_BUILDER_ERROR, INTENT_ERROR, LLM_EXECUTION_ERRORINTERNAL
INGESTION_ERROR, TRANSFORMER_ERRORINVALID_ARGUMENT
FEDERATED_TIMEOUTDEADLINE_EXCEEDED
PLATFORM_SERVICE_ERRORUNAVAILABLE

Two decorator variants exist:

DecoratorUse Case
@grpc_error_handlerUnary RPCs (async def method(request, context))
@grpc_stream_error_handlerStreaming RPCs (async def method(request, context) → AsyncIterator)

ErrorRegistry

The ErrorRegistry provides protocol-level error mapping — reconstruct exceptions from wire codes:

from contextunity.core.exceptions import error_registry
# Create exception from error code string (e.g., from gRPC trailing metadata)
exc = error_registry.from_code("SECURITY_ERROR", message="Token expired")
# → SecurityError("Token expired")
# List all registered codes
codes = error_registry.all_codes()

Service-Specific Subclasses

Services may define thin subclasses for domain-specific categorization:

# In services/brain/
class ContextbrainError(ContextUnityError):
"""Brain-specific error for domain context."""
pass

Module Layout

packages/core/src/contextunity/core/
├── exceptions.py # Exception hierarchy + ErrorRegistry
└── grpc_errors.py # @grpc_error_handler, @grpc_stream_error_handler, status mapping

Import rule: from contextunity.core.exceptions import ... for exception classes, from contextunity.core.grpc_errors import ... for gRPC decorators. Never import gRPC decorators from exceptions.py.