@@ -6,7 +6,7 @@ The Replane SDK uses a hierarchy of exceptions to help you handle errors appropr
66
77```
88ReplaneError (base class)
9- ├── ConfigNotFoundError
9+ ├── ConfigNotFoundError (used for required configs at init time)
1010├── TimeoutError
1111├── AuthenticationError
1212├── NetworkError
@@ -15,13 +15,15 @@ ReplaneError (base class)
1515└── MissingDependencyError
1616```
1717
18+ Note: Accessing a missing config via ` client.configs["name"] ` raises a standard ` KeyError ` , not ` ConfigNotFoundError ` . Use ` client.configs.get("name", default) ` to avoid exceptions.
19+
1820## Error Codes
1921
2022Each ` ReplaneError ` has a ` code ` attribute from the ` ErrorCode ` enum:
2123
2224| Code | Description |
2325| -------------------- | --------------------------------------- |
24- | ` not_found ` | Config doesn't exist |
26+ | ` not_found ` | Config doesn't exist (required configs) |
2527| ` timeout ` | Operation timed out |
2628| ` network_error ` | Network request failed |
2729| ` auth_error ` | Authentication failed (invalid SDK key) |
@@ -41,7 +43,6 @@ Each `ReplaneError` has a `code` attribute from the `ErrorCode` enum:
4143from replane import (
4244 Replane,
4345 ReplaneError,
44- ConfigNotFoundError,
4546 TimeoutError ,
4647 AuthenticationError,
4748)
5152 base_url = " https://replane.example.com" ,
5253 sdk_key = " rp_..." ,
5354 ) as replane:
54- value = replane.get( " my-config" )
55- except ConfigNotFoundError as e:
56- print (f " Config ' { e.config_name } ' not found" )
55+ value = replane.configs[ " my-config" ]
56+ except KeyError as e:
57+ print (f " Config not found: { e } " )
5758except TimeoutError as e:
5859 print (f " Timed out after { e.timeout_ms} ms " )
5960except AuthenticationError:
@@ -68,12 +69,9 @@ except ReplaneError as e:
6869from replane import ReplaneError, ErrorCode
6970
7071try :
71- value = replane.get( " config " )
72+ replane.connect( )
7273except ReplaneError as e:
7374 match e.code:
74- case ErrorCode.NOT_FOUND :
75- # Handle missing config
76- value = default_value
7775 case ErrorCode.TIMEOUT :
7876 # Maybe retry
7977 pass
@@ -87,38 +85,56 @@ except ReplaneError as e:
8785
8886## Specific Exceptions
8987
90- ### ConfigNotFoundError
88+ ### KeyError (Missing Config)
9189
92- Raised when requesting a config that doesn't exist.
90+ Accessing a missing config via bracket notation raises a standard ` KeyError ` :
9391
9492``` python
95- from replane import ConfigNotFoundError
96-
9793try :
98- value = replane.get(" nonexistent-config" )
99- except ConfigNotFoundError as e:
100- print (f " Config not found: { e.config_name} " )
101- # Use a default value instead
94+ value = replane.configs[" nonexistent-config" ]
95+ except KeyError as e:
96+ print (f " Config not found: { e} " )
10297 value = " default"
10398```
10499
105- ** Attributes:**
106-
107- - ` config_name: str ` - Name of the missing config
108-
109- ** Prevention:** Use ` default ` parameter or ` defaults ` option:
100+ ** Prevention:** Use ` .get() ` method or ` defaults ` option:
110101
111102``` python
112- # With default
113- value = replane.get(" config" , default = " fallback" )
103+ # With get() method
104+ value = replane.configs. get(" config" , " fallback" )
114105
115106# With defaults during init
116107replane = Replane(
117108 ... ,
118109 defaults = {" config" : " fallback" },
119110)
111+
112+ # With with_defaults()
113+ safe_client = replane.with_defaults({" config" : " fallback" })
114+ value = safe_client.configs[" config" ] # Returns "fallback" if not configured
115+ ```
116+
117+ ### ConfigNotFoundError
118+
119+ Raised when required configs are missing during initialization.
120+
121+ ``` python
122+ from replane import Replane, ConfigNotFoundError
123+
124+ try :
125+ with Replane(
126+ ... ,
127+ required = [" critical-config-1" , " critical-config-2" ],
128+ ) as replane:
129+ pass
130+ except ConfigNotFoundError as e:
131+ print (f " Missing required configs: { e} " )
120132```
121133
134+ ** Attributes:**
135+
136+ - ` config_name: str ` - Name or description of missing config(s)
137+
122138### TimeoutError
123139
124140Raised when an operation exceeds its timeout.
@@ -199,7 +215,7 @@ replane.connect()
199215replane.close()
200216
201217try :
202- replane.get( " config" ) # Raises ClientClosedError
218+ _ = replane.configs[ " config" ] # Raises ClientClosedError
203219except ClientClosedError:
204220 print (" Client was already closed" )
205221```
@@ -215,10 +231,10 @@ replane = Replane(...)
215231replane.connect(wait = False ) # Don't wait
216232
217233try :
218- replane.get( " config" ) # May raise if not ready
234+ _ = replane.configs[ " config" ] # May raise if not ready
219235except NotInitializedError:
220236 replane.wait_for_init() # Wait then retry
221- value = replane.get( " config" )
237+ value = replane.configs[ " config" ]
222238```
223239
224240### MissingDependencyError
@@ -259,22 +275,22 @@ except ReplaneError as e:
2592752 . ** Use defaults** for resilience against missing configs
2602763 . ** Log errors** with their codes for debugging
2612774 . ** Don't catch and ignore** - at minimum, log the error
262- 5 . ** Use ` default ` parameter ** instead of catching ` ConfigNotFoundError ` when appropriate
278+ 5 . ** Use ` .get() ` method ** instead of catching ` KeyError ` when appropriate
263279
264280``` python
265281# Good: specific handling
266282try :
267- value = replane.get( " critical-config" )
268- except ConfigNotFoundError :
283+ value = replane.configs[ " critical-config" ]
284+ except KeyError :
269285 logger.error(" Critical config missing!" )
270286 raise # Re-raise for critical configs
271287
272288# Good: graceful fallback
273- value = replane.get(" optional-config" , default = " safe-default" )
289+ value = replane.configs. get(" optional-config" , " safe-default" )
274290
275291# Bad: silently ignoring
276292try :
277- value = replane.get( " config" )
278- except ReplaneError :
293+ value = replane.configs[ " config" ]
294+ except KeyError :
279295 pass # Don't do this!
280296```
0 commit comments