Coverage for src/lexigram/graphql/exceptions.py: 100%
61 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-25 04:37 +0800
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-25 04:37 +0800
1"""GraphQL exceptions - complete exception hierarchy."""
3from __future__ import annotations
5from typing import Any
7from lexigram.contracts.exceptions import (
8 AuthenticationError as _ContractsAuthenticationError,
9)
10from lexigram.contracts.exceptions import (
11 AuthorizationError as _ContractsAuthorizationError,
12)
13from lexigram.contracts.exceptions import LexigramError
14from lexigram.graphql.types import GraphQLErrorCode
17class GraphQLError(LexigramError):
18 """Base exception for all GraphQL errors."""
20 _code: str = "LEX_ERR_GQL_001"
21 code: GraphQLErrorCode = GraphQLErrorCode.INTERNAL_SERVER_ERROR
22 safe: bool = False # Whether error message can be shown to users
24 def __init__(
25 self, message: str, *, code: GraphQLErrorCode | None = None, **kwargs: Any
26 ) -> None:
27 # Use class attribute code if not explicitly provided
28 effective_code = code if code is not None else self.__class__.code
29 super().__init__(message)
30 self.code = effective_code
31 self.extensions = kwargs
34class ExecutionError(GraphQLError):
35 """Raised when execution fails."""
37 _code: str = "LEX_ERR_GQL_002"
40class GraphQLTimeoutError(ExecutionError):
41 """Raised when execution times out."""
43 _code: str = "LEX_ERR_GQL_003"
46class QueryTooDeepError(GraphQLError):
47 """Raised when a GraphQL query exceeds the maximum depth."""
49 _code: str = "LEX_ERR_GQL_004"
50 code = GraphQLErrorCode.QUERY_TOO_DEEP
51 safe = True
54# --- Validation ---
55class InputGraphQLError(GraphQLError):
56 """Raised for invalid user input."""
58 _code: str = "LEX_ERR_GQL_005"
59 code = GraphQLErrorCode.BAD_USER_INPUT
60 safe = True
63class ParseError(GraphQLError):
64 """Raised when query parsing fails."""
66 _code: str = "LEX_ERR_GQL_006"
67 code = GraphQLErrorCode.GRAPHQL_PARSE_FAILED
70class QueryTooComplexError(GraphQLError):
71 """Raised when query exceeds complexity limit."""
73 _code: str = "LEX_ERR_GQL_007"
74 code = GraphQLErrorCode.QUERY_TOO_COMPLEX
75 safe = True
78class ResolverError(GraphQLError):
79 """Raised when a resolver fails."""
81 _code: str = "LEX_ERR_GQL_008"
84# --- Auth ---
85class AuthenticationError(GraphQLError, _ContractsAuthenticationError):
86 """Raised when authentication is required but missing.
88 Also satisfies ``lexigram.contracts.exceptions.AuthenticationError`` so
89 middleware that catches the contracts type will catch this as well.
90 """
92 _code: str = "LEX_ERR_GQL_009"
93 code = GraphQLErrorCode.UNAUTHENTICATED
94 safe = True
97class AuthorizationError(GraphQLError, _ContractsAuthorizationError):
98 """Raised when user is authenticated but lacks permissions.
100 Also satisfies ``lexigram.contracts.exceptions.AuthorizationError`` so
101 middleware that catches the contracts type will catch this as well.
102 """
104 _code: str = "LEX_ERR_GQL_010"
105 code = GraphQLErrorCode.UNAUTHORIZED
106 safe = True
109class ForbiddenError(GraphQLError):
110 """Raised when access is forbidden."""
112 _code: str = "LEX_ERR_GQL_011"
113 code = GraphQLErrorCode.FORBIDDEN
114 safe = True
117class NotFoundError(GraphQLError):
118 """Raised when a requested resource is not found."""
120 _code: str = "LEX_ERR_GQL_012"
121 code = GraphQLErrorCode.NOT_FOUND
122 safe = True
125# --- Security ---
126class RateLimitError(GraphQLError):
127 """Raised when rate limit is exceeded."""
129 _code: str = "LEX_ERR_GQL_013"
130 code = GraphQLErrorCode.RATE_LIMITED
131 safe = True
134# --- Subscriptions ---
135class SubscriptionError(GraphQLError):
136 """Raised for subscription-related errors."""
138 _code: str = "LEX_ERR_GQL_014"
141# --- Network ---
142class GraphQLConnectionError(GraphQLError):
143 """Raised when a network connection error occurs during GraphQL execution."""
145 _code: str = "LEX_ERR_GQL_015"
148__all__ = [
149 # Auth
150 "AuthenticationError",
151 "AuthorizationError",
152 # Execution
153 "ExecutionError",
154 "ForbiddenError",
155 # Network
156 "GraphQLConnectionError",
157 # Base
158 "GraphQLError",
159 "GraphQLTimeoutError",
160 # Validation
161 "InputGraphQLError",
162 "NotFoundError",
163 "ParseError",
164 "QueryTooComplexError",
165 "QueryTooDeepError",
166 # Security
167 "RateLimitError",
168 "ResolverError",
169 # Subscriptions
170 "SubscriptionError",
171]