0
# Error Handling
1
2
Configuration-specific error classes for handling invalid authentication and configuration validation failures.
3
4
## Capabilities
5
6
### ErrInvalidAuth Error Class
7
8
Error class for invalid authentication configuration, typically thrown when authentication credentials are malformed or missing required components.
9
10
```javascript { .api }
11
const { ErrInvalidAuth } = require('@npmcli/config/lib/errors');
12
13
/**
14
* Error thrown when authentication configuration is invalid
15
* Extends the standard Error class with problem details
16
*/
17
class ErrInvalidAuth extends Error {
18
/**
19
* Create an invalid authentication error
20
* @param problems - Array of authentication problems found
21
*/
22
constructor(problems: AuthProblem[]);
23
24
/** Error message describing the authentication problems */
25
message: string;
26
27
/** Error code, always "ERR_INVALID_AUTH" */
28
code: string;
29
30
/** Array of authentication problems */
31
problems: AuthProblem[];
32
33
/** Error name, always "ErrInvalidAuth" */
34
name: string;
35
}
36
37
interface AuthProblem {
38
/** Action required to fix the problem ('delete', 'rename') */
39
action: 'delete' | 'rename';
40
/** Configuration key that has the problem */
41
key?: string;
42
/** Source key that needs renaming (for 'rename' action) */
43
from?: string;
44
/** Target key for renaming (for 'rename' action) */
45
to?: string;
46
/** Configuration location where problem exists */
47
where: string;
48
}
49
```
50
51
**Usage Examples:**
52
53
```javascript
54
const { ErrInvalidAuth } = require('@npmcli/config/lib/errors');
55
56
// Catching authentication errors
57
try {
58
// This would be called internally by config validation
59
config.validate();
60
} catch (error) {
61
if (error instanceof ErrInvalidAuth) {
62
console.error('Authentication configuration problems found:');
63
console.error(error.message);
64
65
// Examine specific problems
66
error.problems.forEach(problem => {
67
if (problem.action === 'delete') {
68
console.log(`Remove invalid key '${problem.key}' from ${problem.where} config`);
69
} else if (problem.action === 'rename') {
70
console.log(`Rename '${problem.from}' to '${problem.to}' in ${problem.where} config`);
71
}
72
});
73
74
console.log('Run `npm config fix` to repair your configuration.');
75
}
76
}
77
78
// Throwing authentication errors in custom validation code
79
function validateAuthConfig(configData, where) {
80
const problems = [];
81
82
// Check for deprecated auth keys
83
if (configData['_authtoken']) {
84
problems.push({
85
action: 'rename',
86
from: '_authtoken',
87
to: '_authToken',
88
where: where
89
});
90
}
91
92
// Check for invalid keys in wrong locations
93
if (where === 'global' && configData['_authToken']) {
94
problems.push({
95
action: 'delete',
96
key: '_authToken',
97
where: where
98
});
99
}
100
101
if (problems.length > 0) {
102
throw new ErrInvalidAuth(problems);
103
}
104
}
105
```
106
107
### Common Authentication Error Scenarios
108
109
The `ErrInvalidAuth` error is typically thrown in the following scenarios:
110
111
**Missing Credentials:**
112
```javascript
113
// No authentication provided for private registry
114
try {
115
config.getCredentialsByURI('https://private-registry.com/');
116
} catch (error) {
117
// ErrInvalidAuth: No authentication credentials found for registry
118
}
119
```
120
121
**Incomplete Credentials:**
122
```javascript
123
// Username without password
124
config.setCredentialsByURI('https://registry.com/', {
125
username: 'john',
126
// Missing password
127
});
128
// Throws: ErrInvalidAuth: Username provided but password missing
129
```
130
131
**Invalid Token Format:**
132
```javascript
133
// Malformed authentication token
134
config.setCredentialsByURI('https://registry.npmjs.org/', {
135
token: 'invalid-token-format'
136
});
137
// Throws: ErrInvalidAuth: Invalid token format for registry
138
```
139
140
**Conflicting Authentication Methods:**
141
```javascript
142
// Both token and username/password provided
143
config.setCredentialsByURI('https://registry.com/', {
144
token: 'npm_abc123',
145
username: 'john',
146
password: 'secret'
147
});
148
// Throws: ErrInvalidAuth: Cannot use both token and username/password authentication
149
```
150
151
### Error Handling Best Practices
152
153
**Comprehensive Error Handling:**
154
155
```javascript
156
const { ErrInvalidAuth } = require('@npmcli/config/lib/errors');
157
158
async function setupAuthentication(config, registry, credentials) {
159
try {
160
// Validate credentials before setting
161
if (!credentials) {
162
throw new ErrInvalidAuth('No credentials provided', registry);
163
}
164
165
// Set credentials
166
config.setCredentialsByURI(registry, credentials);
167
168
// Save to user configuration
169
await config.save('user');
170
171
console.log(`Authentication configured for ${registry}`);
172
173
} catch (error) {
174
if (error instanceof ErrInvalidAuth) {
175
console.error(`Authentication Error: ${error.message}`);
176
console.error(`Registry: ${error.registry}`);
177
178
// Provide specific guidance based on registry
179
if (error.registry.includes('npmjs.org')) {
180
console.log('\nTo fix this:');
181
console.log('1. Run: npm login');
182
console.log('2. Or set NPM_TOKEN environment variable');
183
} else {
184
console.log('\nTo fix this:');
185
console.log('1. Contact your registry administrator');
186
console.log('2. Ensure you have valid credentials');
187
console.log('3. Check registry URL is correct');
188
}
189
190
return false;
191
} else {
192
// Re-throw non-authentication errors
193
throw error;
194
}
195
}
196
197
return true;
198
}
199
```
200
201
**Graceful Degradation:**
202
203
```javascript
204
async function getRegistryCredentials(config, registry) {
205
try {
206
const credentials = config.getCredentialsByURI(registry);
207
return credentials;
208
} catch (error) {
209
if (error instanceof ErrInvalidAuth) {
210
console.warn(`No valid credentials for ${registry}, using anonymous access`);
211
return null;
212
}
213
throw error;
214
}
215
}
216
```
217
218
**Validation Before Operations:**
219
220
```javascript
221
function validateAuthenticationSetup(config, requiredRegistries) {
222
const errors = [];
223
224
for (const registry of requiredRegistries) {
225
try {
226
const credentials = config.getCredentialsByURI(registry);
227
if (!credentials) {
228
errors.push(new ErrInvalidAuth('No credentials configured', registry));
229
}
230
} catch (error) {
231
if (error instanceof ErrInvalidAuth) {
232
errors.push(error);
233
}
234
}
235
}
236
237
if (errors.length > 0) {
238
console.error('Authentication validation failed:');
239
errors.forEach(error => {
240
console.error(`- ${error.registry}: ${error.message}`);
241
});
242
return false;
243
}
244
245
return true;
246
}
247
```
248
249
### Error Properties and Methods
250
251
```javascript { .api }
252
// Error instance properties
253
interface ErrInvalidAuth extends Error {
254
/** Error name, always "ErrInvalidAuth" */
255
name: "ErrInvalidAuth";
256
257
/** Descriptive error message */
258
message: string;
259
260
/** Registry URL where authentication failed */
261
registry: string;
262
263
/** Error stack trace */
264
stack?: string;
265
}
266
267
// Error detection
268
function isAuthError(error: any): error is ErrInvalidAuth {
269
return error instanceof ErrInvalidAuth || error.name === 'ErrInvalidAuth';
270
}
271
```
272
273
**Usage in Error Detection:**
274
275
```javascript
276
function handleConfigError(error) {
277
if (error instanceof ErrInvalidAuth) {
278
// Handle authentication errors
279
return handleAuthenticationError(error);
280
} else if (error.code === 'ENOENT') {
281
// Handle file not found errors
282
return handleFileError(error);
283
} else {
284
// Handle other errors
285
return handleGenericError(error);
286
}
287
}
288
```