Skip to content

Index

pyvider.cty.exceptions

TODO: Add module docstring.

Classes

AttributePathError

AttributePathError(
    message: str,
    path: object = None,
    value: object = None,
    **kwargs: Any
)

Bases: CtyError

Raised when there's an error with an attribute path.

This exception occurs when a path operation fails, such as: - When a path cannot be applied to a value - When a path step refers to a non-existent attribute or index - When a path operation is applied to an incompatible value type

Attributes:

Name Type Description
message

A human-readable error description

path

The path that caused the error

value

The value the path was being applied to

Initializes the AttributePathError.

Parameters:

Name Type Description Default
message str

The base error message.

required
path object

The CtyPath or path representation that caused the error.

None
value object

The CtyValue to which the path was being applied.

None
Source code in pyvider/cty/exceptions/encoding.py
def __init__(self, message: str, path: object = None, value: object = None, **kwargs: Any) -> None:
    """
    Initializes the AttributePathError.

    Args:
        message: The base error message.
        path: The CtyPath or path representation that caused the error.
        value: The CtyValue to which the path was being applied.
    """
    self.path = path
    self.value = value

    # Add path operation context
    context: dict[str, Any] = kwargs.setdefault("context", {})
    context["cty.error_category"] = "path_operation"
    context["cty.operation"] = "attribute_path_access"

    if path is not None:
        context["cty.path"] = str(path)
        if hasattr(path, "steps"):
            steps = cast(list[Any], path.steps)
            context["cty.path_depth"] = len(steps)

    if value is not None:
        context["cty.value_type"] = type(value).__name__
        if hasattr(value, "type"):
            context["cty.cty_type"] = str(value.type)

    super().__init__(message, **kwargs)
Functions

CtyCollectionValidationError

CtyCollectionValidationError(
    message: str,
    value: object = None,
    type_name: str | None = None,
    path: CtyPath | None = None,
    **kwargs: Any
)

Bases: CtyValidationError

Base for collection-related validation errors.

Source code in pyvider/cty/exceptions/validation.py
def __init__(
    self,
    message: str,
    value: object = None,
    type_name: str | None = None,
    path: CtyPath | None = None,
    **kwargs: Any,
) -> None:
    self.value = value
    self.type_name = type_name
    self.path = path
    self.message = message

    # Add rich context to foundation error with more detailed information
    context = kwargs.setdefault("context", {})

    # Core CTY context
    if type_name:
        context["cty.type"] = type_name
    if path:
        context["cty.path"] = str(path)
        context["cty.path_depth"] = len(path.steps) if path else 0

    # Value context with safe representation
    if value is not None:
        context["cty.value_type"] = type(value).__name__
        # Safe value representation for debugging (truncated to avoid huge objects)
        try:
            value_repr = repr(value)
            context["cty.value_repr"] = value_repr[:200] + "..." if len(value_repr) > 200 else value_repr
        except Exception:
            context["cty.value_repr"] = f"<repr failed for {type(value).__name__}>"

    # Add validation context if available
    context["cty.validation_stage"] = "type_validation"

    super().__init__(self.message, **kwargs)

CtyConversionError

CtyConversionError(
    message: str,
    *,
    source_value: object | None = None,
    target_type: object | None = None,
    **kwargs: Any
)

Bases: CtyError

Base for CTY value or type conversion errors.

Initializes the CtyConversionError.

Parameters:

Name Type Description Default
message str

The base error message.

required
source_value object | None

The value that was being converted.

None
target_type object | None

The intended target type of the conversion.

None
**kwargs Any

Additional foundation error context.

{}
Source code in pyvider/cty/exceptions/conversion.py
def __init__(
    self,
    message: str,
    *,
    source_value: object | None = None,
    target_type: object | None = None,
    **kwargs: Any,
) -> None:
    """
    Initializes the CtyConversionError.

    Args:
        message: The base error message.
        source_value: The value that was being converted.
        target_type: The intended target type of the conversion.
        **kwargs: Additional foundation error context.
    """
    self.source_value = source_value
    self.target_type = target_type

    # Add rich conversion context
    context = kwargs.setdefault("context", {})
    context["cty.operation"] = "conversion"
    context["cty.error_category"] = "type_conversion"

    # Build message with old format for compatibility
    context_parts = []
    if source_value is not None:
        context_parts.append(f"source_type={type(source_value).__name__}")
        # Also add to foundation context
        context["conversion.source_type"] = type(source_value).__name__
        context["conversion.source_value_type"] = type(source_value).__name__

        # Add value analysis for better debugging
        if hasattr(source_value, "type") and hasattr(source_value, "is_null"):
            context["conversion.source_cty_type"] = str(source_value.type)
            context["conversion.source_is_null"] = source_value.is_null
            if hasattr(source_value, "is_unknown"):
                context["conversion.source_is_unknown"] = source_value.is_unknown

    if target_type is not None:
        target_name = target_type.__name__ if hasattr(target_type, "__name__") else str(target_type)
        context_parts.append(f"target_type={target_name}")
        context["conversion.target_type"] = target_name
        context["conversion.target_type_str"] = str(target_type)

    if context_parts:
        message = f"{message} ({', '.join(context_parts)})"

    super().__init__(message, **kwargs)
Functions

CtyError

CtyError(
    message: str = "An error occurred in the cty type system",
    **kwargs: Any
)

Bases: FoundationError

Base exception for all pyvider.cty errors.

This is the root exception for all errors that occur within the cty type system. It provides a foundation for more specific error types and can be used to catch any cty-related error.

Now inherits from FoundationError to provide rich context support, telemetry integration, and enhanced diagnostics.

Attributes:

Name Type Description
message

A human-readable error description

Source code in pyvider/cty/exceptions/base.py
def __init__(self, message: str = "An error occurred in the cty type system", **kwargs: Any) -> None:
    self.message = message
    super().__init__(self.message, **kwargs)

CtyFunctionError

CtyFunctionError(
    message: str = "An error occurred during CTY function execution",
    *,
    function_name: str | None = None,
    input_types: list[str] | None = None,
    **kwargs: Any
)

Bases: CtyError

Exception raised for errors during the execution of a CTY standard library function.

Enhanced with rich context support for function name, arguments, and execution details.

Attributes:

Name Type Description
message

A human-readable error description

function_name

Name of the CTY function that failed

Source code in pyvider/cty/exceptions/base.py
def __init__(
    self,
    message: str = "An error occurred during CTY function execution",
    *,
    function_name: str | None = None,
    input_types: list[str] | None = None,
    **kwargs: Any,
) -> None:
    self.function_name = function_name
    self.input_types = input_types or []

    # Add function-specific context
    context: dict[str, Any] = kwargs.setdefault("context", {})
    context["cty.error_category"] = "function_execution"
    context["cty.operation"] = "cty_function"

    if function_name:
        context["cty.function_name"] = function_name

    if input_types:
        context["cty.function_input_types"] = input_types
        context["cty.function_arity"] = len(input_types)

    # Enhance message if function name available
    if function_name:
        message = f"CTY function '{function_name}' failed: {message}"

    super().__init__(message, **kwargs)

CtyTypeConversionError

CtyTypeConversionError(
    message: str,
    *,
    type_name: str | None = None,
    source_value: object | None = None,
    target_type: object | None = None,
    **kwargs: Any
)

Bases: CtyConversionError

CTY type representation conversion failure.

Initializes the CtyTypeConversionError.

Parameters:

Name Type Description Default
message str

The base error message.

required
type_name str | None

The name of the CTY type involved in the conversion failure.

None
source_value object | None

The value that was being converted.

None
target_type object | None

The intended target type of the conversion.

None
Source code in pyvider/cty/exceptions/conversion.py
def __init__(
    self,
    message: str,
    *,
    type_name: str | None = None,
    source_value: object | None = None,
    target_type: object | None = None,
    **kwargs: Any,
) -> None:
    """
    Initializes the CtyTypeConversionError.

    Args:
        message: The base error message.
        type_name: The name of the CTY type involved in the conversion failure.
        source_value: The value that was being converted.
        target_type: The intended target type of the conversion.
    """
    self.type_name = type_name

    # Add type-specific context
    context = kwargs.setdefault("context", {})
    context["cty.conversion_category"] = "type_representation"

    if type_name:
        context["cty.failing_type"] = type_name
        message = f'CTY Type "{type_name}" representation conversion failed: {message}'

    super().__init__(message, source_value=source_value, target_type=target_type, **kwargs)
Functions

CtyTypeParseError

CtyTypeParseError(
    message: str, type_string: str, **kwargs: Any
)

Bases: CtyConversionError

Raised when a CTY type string cannot be parsed.

Source code in pyvider/cty/exceptions/conversion.py
def __init__(self, message: str, type_string: str, **kwargs: Any) -> None:
    self.type_string = type_string

    # Add parsing context
    context = kwargs.setdefault("context", {})
    context["cty.conversion_category"] = "type_parsing"
    context["cty.parse_input"] = str(type_string)[:100]  # Truncate for safety
    context["cty.parse_input_type"] = type(type_string).__name__

    full_message = f"{message}: '{type_string}'"
    super().__init__(full_message, source_value=type_string, **kwargs)

CtyValidationError

CtyValidationError(
    message: str,
    value: object = None,
    type_name: str | None = None,
    path: CtyPath | None = None,
    **kwargs: Any
)

Bases: ValidationError

Base exception for all validation errors.

Inherits from foundation's ValidationError for enhanced diagnostics and automatic retry/circuit breaker support where applicable.

Source code in pyvider/cty/exceptions/validation.py
def __init__(
    self,
    message: str,
    value: object = None,
    type_name: str | None = None,
    path: CtyPath | None = None,
    **kwargs: Any,
) -> None:
    self.value = value
    self.type_name = type_name
    self.path = path
    self.message = message

    # Add rich context to foundation error with more detailed information
    context = kwargs.setdefault("context", {})

    # Core CTY context
    if type_name:
        context["cty.type"] = type_name
    if path:
        context["cty.path"] = str(path)
        context["cty.path_depth"] = len(path.steps) if path else 0

    # Value context with safe representation
    if value is not None:
        context["cty.value_type"] = type(value).__name__
        # Safe value representation for debugging (truncated to avoid huge objects)
        try:
            value_repr = repr(value)
            context["cty.value_repr"] = value_repr[:200] + "..." if len(value_repr) > 200 else value_repr
        except Exception:
            context["cty.value_repr"] = f"<repr failed for {type(value).__name__}>"

    # Add validation context if available
    context["cty.validation_stage"] = "type_validation"

    super().__init__(self.message, **kwargs)
Functions
__str__
__str__() -> str

Creates a user-friendly, path-aware error message.

Source code in pyvider/cty/exceptions/validation.py
def __str__(self) -> str:
    """Creates a user-friendly, path-aware error message."""
    path_str = str(self.path) if self.path and self.path.steps else ""
    core_message = self.message

    if path_str and path_str != "(root)":
        return f"At {path_str}: {core_message}"

    return core_message

DeserializationError

DeserializationError(
    message: str,
    data: object = None,
    format_name: str | None = None,
    **kwargs: Any
)

Bases: EncodingError

Raised when deserialization of data fails.

This exception occurs when serialized data cannot be converted back into a Cty value, such as when the data is corrupt or in an incompatible format.

Attributes:

Name Type Description
message

A human-readable error description

data

The data that failed to deserialize

format_name

The name of the format that was being used

Initializes the DeserializationError.

Parameters:

Name Type Description Default
message str

The base error message.

required
data object

The data that failed to deserialize.

None
format_name str | None

The name of the deserialization format.

None
Source code in pyvider/cty/exceptions/encoding.py
def __init__(
    self,
    message: str,
    data: object = None,
    format_name: str | None = None,
    **kwargs: Any,
) -> None:
    """
    Initializes the DeserializationError.

    Args:
        message: The base error message.
        data: The data that failed to deserialize.
        format_name: The name of the deserialization format.
    """
    # Add deserialization-specific context
    context: dict[str, Any] = kwargs.setdefault("context", {})
    context["cty.serialization_direction"] = "deserialize"

    if data is not None:
        if hasattr(data, "__len__"):
            data_with_len = cast(list[Any] | dict[Any, Any] | str | bytes, data)
            context["cty.deserialized_data_size"] = len(data_with_len)
        else:
            context["cty.deserialized_data_size"] = "unknown"

    super().__init__(message, data, format_name, **kwargs)
Functions

DynamicValueError

DynamicValueError(message: str, value: object = None)

Bases: SerializationError

Raised when there's an error encoding or decoding a DynamicValue.

This exception is specific to the handling of dynamic values in serialization contexts, where type information might be unknown or ambiguous.

Attributes:

Name Type Description
message

A human-readable error description

value

The dynamic value that caused the error

Initializes the DynamicValueError.

Parameters:

Name Type Description Default
message str

The base error message.

required
value object

The dynamic value that caused the error.

None
Source code in pyvider/cty/exceptions/encoding.py
def __init__(self, message: str, value: object = None) -> None:
    """
    Initializes the DynamicValueError.

    Args:
        message: The base error message.
        value: The dynamic value that caused the error.
    """
    super().__init__(message, value, "DynamicValue")
Functions

EncodingError

EncodingError(
    message: str,
    data: object = None,
    encoding: str | None = None,
    **kwargs: Any
)

Bases: CtyError

Base exception for all encoding/serialization errors.

This exception serves as the parent class for more specific errors related to serialization and deserialization of Cty values.

Attributes:

Name Type Description
message

A human-readable error description

data

The data that caused the encoding error

encoding

The name of the encoding format that was being used

Initializes the EncodingError.

Parameters:

Name Type Description Default
message str

The base error message.

required
data object

The data that was being encoded/decoded when the error occurred.

None
encoding str | None

The name of the encoding format (e.g., "json", "msgpack").

None
Source code in pyvider/cty/exceptions/encoding.py
def __init__(
    self,
    message: str,
    data: object = None,
    encoding: str | None = None,
    **kwargs: Any,
) -> None:
    """
    Initializes the EncodingError.

    Args:
        message: The base error message.
        data: The data that was being encoded/decoded when the error occurred.
        encoding: The name of the encoding format (e.g., "json", "msgpack").
    """
    self.data = data
    self.encoding = encoding
    # Store original message if subclasses want to modify it AFTER super call
    self._original_message = message

    # Add encoding context
    context: dict[str, Any] = kwargs.setdefault("context", {})
    context["cty.error_category"] = "encoding"
    context["cty.operation"] = "serialization"

    if encoding:
        context["cty.encoding_format"] = encoding
        context["encoding.format"] = encoding

    if data is not None:
        context["cty.data_type"] = type(data).__name__
        # Safe data representation for debugging
        try:
            data_repr = repr(data)
            context["encoding.data_preview"] = (
                data_repr[:100] + "..." if len(data_repr) > 100 else data_repr
            )
        except Exception:
            context["encoding.data_preview"] = f"<repr failed for {type(data).__name__}>"

    # Add format information to the message if available
    if encoding is not None and not message.strip().startswith(encoding.upper()):
        # Avoid double-prefixing if subclass already added it
        message = f"{encoding.upper()} encoding error: {message}"

    super().__init__(message, **kwargs)
Functions

InvalidTypeError

InvalidTypeError(
    message: str, invalid_type: object = None, **kwargs: Any
)

Bases: CtyError

Raised when an invalid type is used in a type definition.

This exception occurs when attempting to create a type with invalid parameters or constraints, such as using a non-CtyType instance when a CtyType is required.

Attributes:

Name Type Description
message

A human-readable error description

invalid_type

The invalid type that caused the error

Initializes the InvalidTypeError.

Parameters:

Name Type Description Default
message str

The base error message.

required
invalid_type object

The type object that was found to be invalid.

None
Source code in pyvider/cty/exceptions/encoding.py
def __init__(self, message: str, invalid_type: object = None, **kwargs: Any) -> None:
    """
    Initializes the InvalidTypeError.

    Args:
        message: The base error message.
        invalid_type: The type object that was found to be invalid.
    """
    self.invalid_type = invalid_type

    # Add type validation context
    context: dict[str, Any] = kwargs.setdefault("context", {})
    context["cty.error_category"] = "invalid_type"
    context["cty.validation_stage"] = "type_definition"

    if invalid_type is not None:
        context["cty.invalid_type"] = type(invalid_type).__name__
        context["cty.invalid_type_str"] = str(invalid_type)[:100]  # Truncated for safety

    super().__init__(message, **kwargs)
Functions

JsonEncodingError

JsonEncodingError(
    message: str,
    data: object = None,
    operation: str | None = None,
)

Bases: EncodingError

Raised when JSON encoding or decoding fails.

This exception provides specific context for JSON serialization errors, including details about the specific JSON operation that failed.

Attributes:

Name Type Description
message

A human-readable error description

data

The data that caused the encoding error

operation

The operation that failed (encode/decode)

Initializes the JsonEncodingError.

Parameters:

Name Type Description Default
message str

The base error message.

required
data object

The data involved in the JSON operation.

None
operation str | None

The JSON operation that failed (e.g., "encode", "decode").

None
Source code in pyvider/cty/exceptions/encoding.py
def __init__(self, message: str, data: object = None, operation: str | None = None) -> None:
    """
    Initializes the JsonEncodingError.

    Args:
        message: The base error message.
        data: The data involved in the JSON operation.
        operation: The JSON operation that failed (e.g., "encode", "decode").
    """
    self.operation = operation
    # Pass original message, data, and "json" as encoding to EncodingError
    super().__init__(message, data, "json")
    # Now, self.args[0] is "JSON encoding error: {message}"
    # Prepend operation part if it exists
    if operation and self.encoding:
        current_message = str(self.args[0]) if self.args else ""
        # Remove the "JSON encoding error: " part, add op, then re-add prefix
        base_message = current_message.replace(f"{self.encoding.upper()} encoding error: ", "", 1)
        formatted_message = f"{self.encoding.upper()} {operation} error: {base_message}"
        self.args = (formatted_message, *self.args[1:])
Functions

MsgPackEncodingError

MsgPackEncodingError(
    message: str,
    data: object = None,
    operation: str | None = None,
)

Bases: EncodingError

Raised when MessagePack encoding or decoding fails.

This exception provides specific context for MessagePack serialization errors, including details about the specific MessagePack operation that failed.

Attributes:

Name Type Description
message

A human-readable error description

data

The data that caused the encoding error

operation

The operation that failed (encode/decode)

Initializes the MsgPackEncodingError.

Parameters:

Name Type Description Default
message str

The base error message.

required
data object

The data involved in the MessagePack operation.

None
operation str | None

The MessagePack operation that failed (e.g., "encode", "decode").

None
Source code in pyvider/cty/exceptions/encoding.py
def __init__(self, message: str, data: object = None, operation: str | None = None) -> None:
    """
    Initializes the MsgPackEncodingError.

    Args:
        message: The base error message.
        data: The data involved in the MessagePack operation.
        operation: The MessagePack operation that failed (e.g., "encode", "decode").
    """
    self.operation = operation
    super().__init__(message, data, "msgpack")
    if operation and self.encoding:
        current_message = str(self.args[0]) if self.args else ""
        base_message = current_message.replace(f"{self.encoding.upper()} encoding error: ", "", 1)
        formatted_message = f"{self.encoding.upper()} {operation} error: {base_message}"
        self.args = (formatted_message, *self.args[1:])
Functions

SerializationError

SerializationError(
    message: str,
    value: object = None,
    format_name: str | None = None,
    **kwargs: Any
)

Bases: EncodingError

Raised when serialization of a value fails.

This exception occurs when a Cty value cannot be serialized to a particular format, such as when a value contains types that aren't supported by the serialization format.

Attributes:

Name Type Description
message

A human-readable error description

value

The value that failed to serialize

format_name

The name of the format that was being used

Initializes the SerializationError.

Parameters:

Name Type Description Default
message str

The base error message.

required
value object

The value that failed to serialize.

None
format_name str | None

The name of the serialization format.

None
Source code in pyvider/cty/exceptions/encoding.py
def __init__(
    self,
    message: str,
    value: object = None,
    format_name: str | None = None,
    **kwargs: Any,
) -> None:
    """
    Initializes the SerializationError.

    Args:
        message: The base error message.
        value: The value that failed to serialize.
        format_name: The name of the serialization format.
    """
    self.value = value

    # Add serialization-specific context
    context: dict[str, Any] = kwargs.setdefault("context", {})
    context["cty.serialization_direction"] = "serialize"

    if value is not None and hasattr(value, "type"):
        context["cty.serialized_cty_type"] = str(value.type)
        if hasattr(value, "is_null"):
            context["cty.serialized_is_null"] = value.is_null

    super().__init__(message, value, format_name, **kwargs)
Functions

TransformationError

TransformationError(
    message: str,
    schema: object = None,
    target_type: object = None,
    **kwargs: object
)

Bases: CtyError

Raised when a schema transformation fails.

This exception occurs when a schema cannot be transformed from one representation to another, such as during conversion between different schema formats or when applying schema transformations.

Attributes:

Name Type Description
message

A human-readable error description

schema

The schema that failed transformation

target_type

The intended target type of a transformation, if applicable

Initializes the TransformationError.

Parameters:

Name Type Description Default
message str

The base error message.

required
schema object

The schema object that was being transformed.

None
target_type object

The intended target type of the transformation.

None
**kwargs object

Additional keyword arguments for foundation error context.

{}
Source code in pyvider/cty/exceptions/encoding.py
def __init__(
    self,
    message: str,
    schema: object = None,
    target_type: object = None,
    **kwargs: object,
) -> None:
    """
    Initializes the TransformationError.

    Args:
        message: The base error message.
        schema: The schema object that was being transformed.
        target_type: The intended target type of the transformation.
        **kwargs: Additional keyword arguments for foundation error context.
    """
    self.schema = schema
    self.target_type = target_type

    # Add rich transformation context
    # kwargs.setdefault returns object, but we know it's dict[str, Any]
    context: dict[str, Any] = kwargs.setdefault("context", {})  # type: ignore[assignment]
    context["cty.operation"] = "schema_transformation"
    context["cty.error_category"] = "transformation"

    if schema is not None:
        context["transformation.schema_type"] = type(schema).__name__
        context["cty.source_schema_type"] = type(schema).__name__

    if target_type is not None:
        target_name = getattr(target_type, "__name__", str(target_type))
        context["transformation.target_type"] = target_name
        context["cty.target_type"] = target_name

    context_parts = []
    if schema is not None:
        context_parts.append(f"schema_type={type(schema).__name__}")
    if target_type is not None:
        target_type_name = getattr(target_type, "__name__", str(target_type))
        context_parts.append(f"target_type={target_type_name}")

    if context_parts:
        message = f"{message} ({', '.join(context_parts)})"

    super().__init__(message, **kwargs)
Functions

WireFormatError

WireFormatError(
    message: str,
    *,
    format_type: object = None,
    operation: str | None = None,
    **kwargs: object
)

Bases: TransformationError

Raised when wire format encoding or decoding fails.

This exception is specific to the wire format system and provides additional context about the operation that failed.

Attributes:

Name Type Description
message

A human-readable error description

format_type

The wire format type that encountered an error

operation

The operation that failed (marshal/unmarshal)

Initializes the WireFormatError.

Parameters:

Name Type Description Default
message str

The base error message.

required
format_type object

The wire format type that encountered the error.

None
operation str | None

The wire format operation that failed (e.g., "marshal", "unmarshal").

None
**kwargs object

Additional arguments for the parent TransformationError.

{}
Source code in pyvider/cty/exceptions/encoding.py
def __init__(
    self,
    message: str,
    *,
    format_type: object = None,
    operation: str | None = None,
    **kwargs: object,  # Catches schema, target_type for TransformationError
) -> None:
    """
    Initializes the WireFormatError.

    Args:
        message: The base error message.
        format_type: The wire format type that encountered the error.
        operation: The wire format operation that failed (e.g., "marshal", "unmarshal").
        **kwargs: Additional arguments for the parent TransformationError.
    """
    self.format_type = format_type
    self.operation = operation

    # Initialize TransformationError with the original message and its specific args
    super().__init__(message, schema=kwargs.get("schema"), target_type=kwargs.get("target_type"))

    # self.args[0] now contains message possibly formatted by TransformationError
    # Append WireFormatError specific details to it
    current_message = str(self.args[0]) if self.args else ""

    if format_type is not None:
        format_info = f" using {format_type}"
        if operation:
            format_info = f" during {operation}{format_info}"
        current_message = f"{current_message}{format_info}"
    elif operation:  # Only operation is present, no format_type
        current_message = f"{current_message} during {operation}"

    self.args = (current_message, *self.args[1:])
Functions