0
# Error Handling
1
2
Comprehensive exception hierarchy for handling template processing errors, configuration issues, user interaction problems, and system-level failures in copier operations.
3
4
## Capabilities
5
6
### Base Exceptions
7
8
Foundation exception classes for all copier errors and warnings.
9
10
```python { .api }
11
class CopierError(Exception):
12
"""Base class for all Copier errors."""
13
14
class CopierWarning(UserWarning):
15
"""Base class for all Copier warnings."""
16
```
17
18
### User-Facing Exceptions
19
20
Exceptions that indicate user-level issues requiring user action or input.
21
22
```python { .api }
23
class UserMessageError(CopierError):
24
"""Exit program with user message."""
25
26
class UnsupportedVersionError(CopierError):
27
"""Copier version doesn't support this template."""
28
29
class InteractiveSessionError(CopierError):
30
"""Interactive session required but not available."""
31
```
32
33
Usage examples:
34
35
```python
36
from copier import run_copy
37
from copier.errors import UserMessageError, UnsupportedVersionError
38
39
try:
40
worker = run_copy("template/", "project/")
41
except UserMessageError as e:
42
print(f"User error: {e}")
43
# Handle user-facing error gracefully
44
except UnsupportedVersionError as e:
45
print(f"Version compatibility issue: {e}")
46
# Suggest upgrading copier or using different template version
47
```
48
49
### Configuration Exceptions
50
51
Exceptions related to template configuration files and settings.
52
53
```python { .api }
54
class ConfigFileError(CopierError):
55
"""Base class for config file problems."""
56
57
class InvalidConfigFileError(ConfigFileError):
58
"""Invalid config file format or content."""
59
60
class MultipleConfigFilesError(ConfigFileError):
61
"""Multiple config files found in template."""
62
```
63
64
Usage examples:
65
66
```python
67
from copier import run_copy
68
from copier.errors import ConfigFileError, InvalidConfigFileError
69
70
try:
71
worker = run_copy("template/", "project/")
72
except InvalidConfigFileError as e:
73
print(f"Template configuration error: {e}")
74
# Check copier.yml or copier.yaml in template
75
except MultipleConfigFilesError as e:
76
print(f"Conflicting config files: {e}")
77
# Remove duplicate configuration files
78
```
79
80
### Path-Related Exceptions
81
82
Exceptions for file system path validation and access issues.
83
84
```python { .api }
85
class PathError(CopierError):
86
"""Base class for path-related errors."""
87
88
class PathNotAbsoluteError(PathError):
89
"""Path should be absolute but is relative."""
90
91
class PathNotRelativeError(PathError):
92
"""Path should be relative but is absolute."""
93
94
class ForbiddenPathError(PathError):
95
"""Path is forbidden for security reasons."""
96
```
97
98
Usage examples:
99
100
```python
101
from copier import Worker
102
from copier.errors import PathError, ForbiddenPathError
103
104
try:
105
worker = Worker(
106
src_path="template/",
107
dst_path="../../../etc/passwd" # Dangerous path
108
)
109
worker.run_copy()
110
except ForbiddenPathError as e:
111
print(f"Security violation: {e}")
112
# Use safe destination path
113
except PathError as e:
114
print(f"Path issue: {e}")
115
# Validate and correct path
116
```
117
118
### Template Processing Exceptions
119
120
Exceptions that occur during template processing and rendering.
121
122
```python { .api }
123
class InvalidTypeError(CopierError):
124
"""Unsupported question type in template."""
125
126
class ExtensionNotFoundError(CopierError):
127
"""Template extensions couldn't be loaded."""
128
129
class UnsafeTemplateError(CopierError):
130
"""Template contains unsafe features without user consent."""
131
132
class YieldTagInFileError(CopierError):
133
"""Yield tag found in file content (not allowed)."""
134
135
class MultipleYieldTagsError(CopierError):
136
"""Multiple yield tags found in path name."""
137
138
class TaskError(CopierError):
139
"""Task execution failed during template processing."""
140
141
@classmethod
142
def from_process(cls, process: subprocess.CompletedProcess) -> TaskError:
143
"""Create TaskError from a failed subprocess."""
144
```
145
146
Usage examples:
147
148
```python
149
from copier import run_copy
150
from copier.errors import UnsafeTemplateError, TaskError
151
152
try:
153
worker = run_copy(
154
"suspicious-template/",
155
"project/",
156
unsafe=False # Reject unsafe templates
157
)
158
except UnsafeTemplateError as e:
159
print(f"Template safety issue: {e}")
160
# Review template or use unsafe=True if trusted
161
except TaskError as e:
162
print(f"Template task failed: {e}")
163
# Check template tasks configuration
164
```
165
166
### User Interaction Exceptions
167
168
Exceptions related to user input and interactive sessions.
169
170
```python { .api }
171
class CopierAnswersInterrupt(CopierError):
172
"""Keyboard interrupt during questionnaire."""
173
```
174
175
Usage examples:
176
177
```python
178
from copier import run_copy
179
from copier.errors import CopierAnswersInterrupt
180
181
try:
182
worker = run_copy("template/", "project/")
183
except CopierAnswersInterrupt:
184
print("Operation cancelled by user")
185
# Clean up partial work if needed
186
except KeyboardInterrupt:
187
print("Process interrupted")
188
# Handle general interruption
189
```
190
191
### Warning Classes
192
193
Warning classes for non-fatal issues that don't stop processing.
194
195
```python { .api }
196
class UnknownCopierVersionWarning(CopierWarning):
197
"""Cannot determine which Copier version was used."""
198
199
class OldTemplateWarning(CopierWarning):
200
"""Template was designed for an older Copier version."""
201
202
class DirtyLocalWarning(CopierWarning):
203
"""Uncommitted changes in local template directory."""
204
205
class ShallowCloneWarning(CopierWarning):
206
"""Template repository is a shallow clone."""
207
208
class MissingSettingsWarning(CopierWarning):
209
"""Settings file not found at expected location."""
210
211
class MissingFileWarning(CopierWarning):
212
"""Referenced file not found in template."""
213
```
214
215
Usage examples:
216
217
```python
218
import warnings
219
from copier import run_copy
220
from copier.errors import OldTemplateWarning, DirtyLocalWarning
221
222
# Configure warning handling
223
warnings.filterwarnings("always", category=OldTemplateWarning)
224
225
try:
226
with warnings.catch_warnings(record=True) as w:
227
worker = run_copy("old-template/", "project/")
228
229
for warning in w:
230
if issubclass(warning.category, DirtyLocalWarning):
231
print(f"Template has uncommitted changes: {warning.message}")
232
elif issubclass(warning.category, OldTemplateWarning):
233
print(f"Template compatibility: {warning.message}")
234
235
except Exception as e:
236
print(f"Processing failed: {e}")
237
```
238
239
### Exception Hierarchy Summary
240
241
```python
242
CopierError
243
├── UserMessageError
244
├── UnsupportedVersionError
245
├── ConfigFileError
246
│ ├── InvalidConfigFileError
247
│ └── MultipleConfigFilesError
248
├── PathError
249
│ ├── PathNotAbsoluteError
250
│ ├── PathNotRelativeError
251
│ └── ForbiddenPathError
252
├── InvalidTypeError
253
├── ExtensionNotFoundError
254
├── CopierAnswersInterrupt
255
├── UnsafeTemplateError
256
├── YieldTagInFileError
257
├── MultipleYieldTagsError
258
└── TaskError
259
260
CopierWarning
261
├── UnknownCopierVersionWarning
262
├── OldTemplateWarning
263
├── DirtyLocalWarning
264
├── ShallowCloneWarning
265
├── MissingSettingsWarning
266
├── MissingFileWarning
267
└── InteractiveSessionError
268
```
269
270
### Best Practices
271
272
```python
273
from copier import run_copy
274
from copier.errors import CopierError, ConfigFileError, PathError
275
276
def safe_template_processing(template_path: str, output_path: str) -> bool:
277
"""Safely process template with comprehensive error handling."""
278
try:
279
worker = run_copy(template_path, output_path)
280
return True
281
282
except ConfigFileError as e:
283
print(f"Template configuration issue: {e}")
284
# Log for template author to fix
285
return False
286
287
except PathError as e:
288
print(f"Path validation failed: {e}")
289
# Sanitize and retry with safe paths
290
return False
291
292
except CopierError as e:
293
print(f"Copier processing error: {e}")
294
# General copier error handling
295
return False
296
297
except Exception as e:
298
print(f"Unexpected error: {e}")
299
# Handle unexpected system errors
300
return False
301
```