0
# Exception Handling
1
2
Comprehensive exception hierarchy for handling various error conditions in SecretStorage operations. All exceptions derive from the base `SecretStorageException` class, providing structured error handling for different failure scenarios.
3
4
## Capabilities
5
6
### Exception Hierarchy
7
8
SecretStorage defines a clear exception hierarchy for different types of errors that can occur during secret storage operations.
9
10
```python { .api }
11
class SecretStorageException(Exception):
12
"""
13
Base exception class for all SecretStorage errors.
14
15
All other SecretStorage exceptions inherit from this class,
16
allowing for broad exception handling when needed.
17
"""
18
19
class SecretServiceNotAvailableException(SecretStorageException):
20
"""
21
Raised when the Secret Service API is not available.
22
23
This can occur when:
24
- D-Bus session bus is not running
25
- Secret Service daemon (GNOME Keyring, KWallet, etc.) is not installed
26
- Required environment variables are not set
27
- D-Bus connection cannot be established
28
"""
29
30
class LockedException(SecretStorageException):
31
"""
32
Raised when an operation cannot be performed because the collection or item is locked.
33
34
Operations that require unlocked collections/items:
35
- Reading secret data
36
- Creating/modifying items
37
- Deleting collections/items
38
- Setting labels and attributes
39
40
Use unlock() methods to resolve this condition.
41
"""
42
43
class ItemNotFoundException(SecretStorageException):
44
"""
45
Raised when an item or collection does not exist or has been deleted.
46
47
This can occur when:
48
- Accessing an item that was deleted by another process
49
- Using invalid D-Bus object paths
50
- Accessing collections that don't exist
51
- D-Bus objects that have become invalid
52
"""
53
54
class PromptDismissedException(ItemNotFoundException):
55
"""
56
Raised when a user dismisses an authentication or confirmation prompt.
57
58
This can occur during operations that require user interaction:
59
- Unlocking collections or items
60
- Creating new collections
61
- Deleting collections or items
62
- Any operation requiring user authentication
63
"""
64
```
65
66
### Error Handling Patterns
67
68
**Basic Exception Handling:**
69
```python
70
import secretstorage
71
72
try:
73
connection = secretstorage.dbus_init()
74
collection = secretstorage.get_default_collection(connection)
75
item = collection.create_item("Test", {"app": "myapp"}, b"secret")
76
77
except secretstorage.SecretServiceNotAvailableException as e:
78
print(f"Secret service not available: {e}")
79
# Fallback to alternative storage method
80
81
except secretstorage.LockedException as e:
82
print(f"Collection is locked: {e}")
83
# Attempt to unlock or inform user
84
85
except secretstorage.PromptDismissedException as e:
86
print(f"User dismissed prompt: {e}")
87
# Handle user cancellation
88
89
except secretstorage.SecretStorageException as e:
90
print(f"General SecretStorage error: {e}")
91
# Handle any other SecretStorage-specific errors
92
```
93
94
**Handling Locked Collections:**
95
```python
96
import secretstorage
97
98
connection = secretstorage.dbus_init()
99
collection = secretstorage.get_default_collection(connection)
100
101
try:
102
# Attempt operation that requires unlocked collection
103
secret = item.get_secret()
104
105
except secretstorage.LockedException:
106
# Try to unlock
107
try:
108
dismissed = collection.unlock()
109
if dismissed:
110
print("User dismissed unlock prompt")
111
# Handle user cancellation
112
else:
113
# Retry the operation
114
secret = item.get_secret()
115
116
except secretstorage.PromptDismissedException:
117
print("Failed to unlock - user dismissed prompt")
118
# Handle inability to unlock
119
```
120
121
**Service Availability Check:**
122
```python
123
import secretstorage
124
125
try:
126
connection = secretstorage.dbus_init()
127
128
# Check if service is available before proceeding
129
if not secretstorage.check_service_availability(connection):
130
print("Secret service not available")
131
# Use alternative storage
132
else:
133
# Proceed with secret service operations
134
collection = secretstorage.get_default_collection(connection)
135
136
except secretstorage.SecretServiceNotAvailableException:
137
print("Cannot connect to D-Bus or secret service")
138
# Fallback to alternative storage method
139
```
140
141
**Robust Item Creation:**
142
```python
143
import secretstorage
144
145
def store_secret_safely(label, attributes, secret_data):
146
"""Safely store a secret with comprehensive error handling."""
147
try:
148
connection = secretstorage.dbus_init()
149
collection = secretstorage.get_default_collection(connection)
150
151
# Ensure collection is unlocked
152
if collection.is_locked():
153
dismissed = collection.unlock()
154
if dismissed:
155
raise secretstorage.PromptDismissedException("Collection unlock dismissed")
156
157
# Create the item
158
item = collection.create_item(label, attributes, secret_data)
159
return item
160
161
except secretstorage.SecretServiceNotAvailableException:
162
print("Secret service unavailable - using alternative storage")
163
# Implement fallback storage mechanism
164
return None
165
166
except secretstorage.LockedException:
167
print("Cannot unlock collection")
168
return None
169
170
except secretstorage.PromptDismissedException:
171
print("User cancelled operation")
172
return None
173
174
except secretstorage.SecretStorageException as e:
175
print(f"Unexpected secret storage error: {e}")
176
return None
177
```
178
179
**Item Search with Error Handling:**
180
```python
181
import secretstorage
182
183
def find_secrets_safely(attributes):
184
"""Find secrets with proper error handling."""
185
try:
186
connection = secretstorage.dbus_init()
187
items = list(secretstorage.search_items(connection, attributes))
188
189
results = []
190
for item in items:
191
try:
192
# Check if we can access the item
193
if not item.is_locked():
194
secret = item.get_secret()
195
results.append({
196
'label': item.get_label(),
197
'attributes': item.get_attributes(),
198
'secret': secret
199
})
200
else:
201
# Attempt to unlock item
202
dismissed = item.unlock()
203
if not dismissed:
204
secret = item.get_secret()
205
results.append({
206
'label': item.get_label(),
207
'attributes': item.get_attributes(),
208
'secret': secret
209
})
210
211
except secretstorage.ItemNotFoundException:
212
# Item was deleted during iteration
213
continue
214
215
except secretstorage.LockedException:
216
# Item couldn't be unlocked
217
results.append({
218
'label': item.get_label(),
219
'attributes': item.get_attributes(),
220
'secret': None,
221
'locked': True
222
})
223
224
return results
225
226
except secretstorage.SecretServiceNotAvailableException:
227
print("Secret service not available")
228
return []
229
230
except secretstorage.SecretStorageException as e:
231
print(f"Error searching secrets: {e}")
232
return []
233
```
234
235
## Exception Context
236
237
### When Exceptions Occur
238
239
- **SecretServiceNotAvailableException**: During `dbus_init()`, `get_default_collection()`, or any operation when the service becomes unavailable
240
- **LockedException**: When calling `get_secret()`, `set_secret()`, `create_item()`, `delete()`, or `set_label()` on locked collections/items
241
- **ItemNotFoundException**: When accessing deleted items, non-existent collections, or invalid D-Bus paths
242
- **PromptDismissedException**: During `unlock()`, `create_collection()`, `delete()`, or any operation requiring user authentication
243
244
### Best Practices
245
246
1. **Always handle SecretServiceNotAvailableException** for graceful degradation
247
2. **Check lock status** before performing sensitive operations
248
3. **Implement retry logic** for prompt dismissals when appropriate
249
4. **Use specific exception types** rather than catching all exceptions
250
5. **Provide meaningful error messages** to users
251
6. **Have fallback storage mechanisms** for when secret service is unavailable
252
253
## Types
254
255
```python { .api }
256
# All exception classes inherit from Python's built-in Exception class
257
class Exception:
258
"""Base class for all Python exceptions."""
259
```