0
# Error Handling and Diagnostics
1
2
Comprehensive error handling with specific exception types for different failure scenarios in dependency injection and container management.
3
4
## Capabilities
5
6
### Definition and Resolution Errors
7
8
Handle errors related to dependency definition and resolution failures.
9
10
```javascript { .api }
11
/**
12
* Exception thrown when definition is not found during resolution
13
*/
14
class NoDefinitionFoundException extends Error {
15
/**
16
* Create exception for missing definition
17
* @param message - Error description
18
*/
19
constructor(message: string);
20
21
/**
22
* The qualifier that was not found (if any)
23
*/
24
qualifier?: Qualifier;
25
26
/**
27
* The type that was being resolved
28
*/
29
type?: any;
30
}
31
32
/**
33
* Exception thrown when definition override is not allowed
34
*/
35
class DefinitionOverrideException extends Error {
36
/**
37
* Create exception for definition override conflict
38
* @param message - Error description
39
*/
40
constructor(message: string);
41
42
/**
43
* The definition that conflicts
44
*/
45
definition?: BeanDefinition<any>;
46
}
47
48
/**
49
* Exception thrown when instance creation fails
50
*/
51
class InstanceCreationException extends Error {
52
/**
53
* Create exception for instance creation failure
54
* @param message - Error description
55
* @param cause - Underlying cause of failure
56
*/
57
constructor(message: string, cause?: Error);
58
59
/**
60
* The underlying cause of the creation failure
61
*/
62
cause?: Error;
63
64
/**
65
* The definition that failed to create instance
66
*/
67
definition?: BeanDefinition<any>;
68
}
69
```
70
71
**Usage Examples:**
72
73
```javascript
74
import {
75
GlobalContext,
76
NoDefinitionFoundException,
77
DefinitionOverrideException,
78
InstanceCreationException,
79
named
80
} from "koin-core";
81
82
class ServiceManager {
83
async getService(serviceName) {
84
try {
85
const koin = GlobalContext.get();
86
return koin.get(named(serviceName));
87
88
} catch (error) {
89
if (error instanceof NoDefinitionFoundException) {
90
console.error(`Service '${serviceName}' not found in DI container`);
91
console.error(`Qualifier: ${error.qualifier?.value}`);
92
console.error(`Type: ${error.type?.name}`);
93
94
// Provide fallback or default service
95
return this.createFallbackService(serviceName);
96
97
} else if (error instanceof InstanceCreationException) {
98
console.error(`Failed to create service '${serviceName}'`);
99
console.error(`Cause: ${error.cause?.message}`);
100
101
// Log additional context and re-throw
102
this.logCreationFailure(error);
103
throw new Error(`Service creation failed: ${error.message}`);
104
105
} else {
106
// Re-throw unknown errors
107
throw error;
108
}
109
}
110
}
111
112
registerService(serviceName, factory, allowOverride = false) {
113
try {
114
const koin = GlobalContext.get();
115
const module = module((builder) => {
116
builder.single(named(serviceName), factory);
117
});
118
119
if (allowOverride) {
120
// Handle override explicitly
121
koin.declare(factory(), named(serviceName), [], true);
122
} else {
123
loadKoinModules([module]);
124
}
125
126
} catch (error) {
127
if (error instanceof DefinitionOverrideException) {
128
console.error(`Service '${serviceName}' already exists`);
129
console.error(`Existing definition: ${error.definition?.qualifier?.value}`);
130
131
if (allowOverride) {
132
// Force override
133
this.forceOverrideService(serviceName, factory);
134
} else {
135
throw new Error(`Service '${serviceName}' already registered`);
136
}
137
}
138
}
139
}
140
}
141
```
142
143
### Scope-Related Errors
144
145
Handle errors related to scope lifecycle and management.
146
147
```javascript { .api }
148
/**
149
* Exception thrown when attempting to use a closed scope
150
*/
151
class ClosedScopeException extends Error {
152
/**
153
* Create exception for closed scope access
154
* @param scopeId - The ID of the closed scope
155
*/
156
constructor(scopeId: string);
157
158
/**
159
* ID of the scope that was closed
160
*/
161
scopeId: string;
162
}
163
164
/**
165
* Exception thrown when scope doesn't exist
166
*/
167
class ScopeNotCreatedException extends Error {
168
/**
169
* Create exception for non-existent scope
170
* @param scopeId - The ID of the missing scope
171
*/
172
constructor(scopeId: string);
173
174
/**
175
* ID of the scope that doesn't exist
176
*/
177
scopeId: string;
178
}
179
180
/**
181
* Exception thrown when scope already exists
182
*/
183
class ScopeAlreadyCreatedException extends Error {
184
/**
185
* Create exception for duplicate scope creation
186
* @param scopeId - The ID of the existing scope
187
*/
188
constructor(scopeId: string);
189
190
/**
191
* ID of the scope that already exists
192
*/
193
scopeId: string;
194
}
195
196
/**
197
* Exception thrown when scope definition is not found
198
*/
199
class NoScopeDefFoundException extends Error {
200
/**
201
* Create exception for missing scope definition
202
* @param message - Error description
203
*/
204
constructor(message: string);
205
206
/**
207
* The scope qualifier that was not found
208
*/
209
scopeQualifier?: Qualifier;
210
}
211
212
/**
213
* Exception thrown when scope value is missing
214
*/
215
class MissingScopeValueException extends Error {
216
/**
217
* Create exception for missing scope value
218
* @param message - Error description
219
*/
220
constructor(message: string);
221
}
222
```
223
224
**Usage Examples:**
225
226
```javascript
227
import {
228
GlobalContext,
229
ClosedScopeException,
230
ScopeNotCreatedException,
231
ScopeAlreadyCreatedException,
232
NoScopeDefFoundException,
233
named
234
} from "koin-core";
235
236
class ScopeManager {
237
constructor() {
238
this.activeScopes = new Map();
239
}
240
241
async createUserSession(userId) {
242
const scopeId = `session-${userId}`;
243
244
try {
245
const koin = GlobalContext.get();
246
const scope = koin.createScope(scopeId, named("session"));
247
248
this.activeScopes.set(userId, scope);
249
return scope;
250
251
} catch (error) {
252
if (error instanceof ScopeAlreadyCreatedException) {
253
console.warn(`Session scope for user ${userId} already exists`);
254
// Return existing scope
255
return koin.getScope(scopeId);
256
257
} else if (error instanceof NoScopeDefFoundException) {
258
console.error(`Session scope definition not found`);
259
console.error(`Missing scope qualifier: ${error.scopeQualifier?.value}`);
260
throw new Error("Session management not configured");
261
262
} else {
263
throw error;
264
}
265
}
266
}
267
268
async getUserSession(userId) {
269
const scopeId = `session-${userId}`;
270
271
try {
272
const koin = GlobalContext.get();
273
const scope = koin.getScope(scopeId);
274
275
// Try to get user session from scope
276
return scope.get(named("userSession"));
277
278
} catch (error) {
279
if (error instanceof ScopeNotCreatedException) {
280
console.error(`No session scope found for user ${userId}`);
281
// Create new session automatically
282
const newScope = await this.createUserSession(userId);
283
return newScope.get(named("userSession"));
284
285
} else if (error instanceof ClosedScopeException) {
286
console.error(`Session scope for user ${userId} is closed`);
287
// Remove from active scopes and recreate
288
this.activeScopes.delete(userId);
289
const newScope = await this.createUserSession(userId);
290
return newScope.get(named("userSession"));
291
292
} else {
293
throw error;
294
}
295
}
296
}
297
298
async closeUserSession(userId) {
299
const scope = this.activeScopes.get(userId);
300
301
if (scope) {
302
try {
303
scope.close();
304
this.activeScopes.delete(userId);
305
console.log(`Session closed for user ${userId}`);
306
307
} catch (error) {
308
if (error instanceof ClosedScopeException) {
309
// Already closed, just clean up
310
this.activeScopes.delete(userId);
311
} else {
312
throw error;
313
}
314
}
315
}
316
}
317
}
318
```
319
320
### Parameter and Property Errors
321
322
Handle errors related to parameter injection and property access.
323
324
```javascript { .api }
325
/**
326
* Exception thrown when required parameter is not found
327
*/
328
class NoParameterFoundException extends Error {
329
/**
330
* Create exception for missing parameter
331
* @param message - Error description
332
*/
333
constructor(message: string);
334
335
/**
336
* Parameter index that was requested
337
*/
338
parameterIndex?: number;
339
340
/**
341
* Parameter type that was requested
342
*/
343
parameterType?: any;
344
}
345
346
/**
347
* Exception thrown when parameter definition has errors
348
*/
349
class DefinitionParameterException extends Error {
350
/**
351
* Create exception for parameter definition error
352
* @param message - Error description
353
*/
354
constructor(message: string);
355
356
/**
357
* The definition that has parameter issues
358
*/
359
definition?: BeanDefinition<any>;
360
}
361
362
/**
363
* Exception thrown when property is not found
364
*/
365
class MissingPropertyException extends Error {
366
/**
367
* Create exception for missing property
368
* @param key - The property key that was not found
369
*/
370
constructor(key: string);
371
372
/**
373
* The property key that was missing
374
*/
375
key: string;
376
}
377
378
/**
379
* Exception thrown when property file is not found
380
*/
381
class NoPropertyFileFoundException extends Error {
382
/**
383
* Create exception for missing property file
384
* @param message - Error description
385
*/
386
constructor(message: string);
387
388
/**
389
* The property file path that was not found
390
*/
391
filePath?: string;
392
}
393
```
394
395
**Usage Examples:**
396
397
```javascript
398
import {
399
module,
400
parametersOf,
401
NoParameterFoundException,
402
DefinitionParameterException,
403
MissingPropertyException,
404
KoinComponent
405
} from "koin-core";
406
407
const dynamicModule = module((builder) => {
408
builder.factory((scope, params) => {
409
try {
410
// Validate required parameters
411
if (params.isEmpty()) {
412
throw new DefinitionParameterException("Database connection requires parameters");
413
}
414
415
const host = params.elementAt(0);
416
const port = params.elementAt(1);
417
418
if (!host || !port) {
419
throw new DefinitionParameterException("Host and port parameters required");
420
}
421
422
return new DatabaseConnection(host, port);
423
424
} catch (error) {
425
if (error instanceof NoParameterFoundException) {
426
console.error(`Parameter missing: index ${error.parameterIndex}, type ${error.parameterType?.name}`);
427
// Use default parameters
428
return new DatabaseConnection("localhost", 5432);
429
}
430
throw error;
431
}
432
});
433
});
434
435
class ConfigurableService extends KoinComponent {
436
constructor() {
437
super();
438
this.loadConfiguration();
439
}
440
441
loadConfiguration() {
442
try {
443
// Try to load configuration properties
444
this.apiUrl = this.getProperty("api.url");
445
this.timeout = this.getProperty("api.timeout", 5000);
446
this.retries = this.getProperty("api.retries", 3);
447
448
} catch (error) {
449
if (error instanceof MissingPropertyException) {
450
console.error(`Missing required property: ${error.key}`);
451
452
// Provide sensible defaults
453
switch (error.key) {
454
case "api.url":
455
this.apiUrl = "https://api.default.com";
456
break;
457
case "api.timeout":
458
this.timeout = 5000;
459
break;
460
case "api.retries":
461
this.retries = 3;
462
break;
463
default:
464
throw new Error(`Required configuration missing: ${error.key}`);
465
}
466
} else {
467
throw error;
468
}
469
}
470
}
471
472
async createConnection(host, port) {
473
try {
474
const connection = this.get(named("database"), () =>
475
parametersOf(host, port)
476
);
477
return connection;
478
479
} catch (error) {
480
if (error instanceof DefinitionParameterException) {
481
console.error(`Parameter error: ${error.message}`);
482
console.error(`Definition: ${error.definition?.qualifier?.value}`);
483
484
// Try with default parameters
485
const defaultConnection = this.get(named("database"), () =>
486
parametersOf("localhost", 5432)
487
);
488
return defaultConnection;
489
}
490
throw error;
491
}
492
}
493
}
494
```
495
496
### Application State Errors
497
498
Handle errors related to application lifecycle and state management.
499
500
```javascript { .api }
501
/**
502
* Exception thrown when Koin application is already started
503
*/
504
class KoinApplicationAlreadyStartedException extends Error {
505
/**
506
* Create exception for duplicate application start
507
* @param message - Error description
508
*/
509
constructor(message: string);
510
}
511
512
/**
513
* Exception thrown when trying to access Koin before it's started
514
*/
515
class IllegalStateException extends Error {
516
/**
517
* Create exception for illegal state access
518
* @param message - Error description
519
*/
520
constructor(message: string);
521
}
522
```
523
524
**Usage Examples:**
525
526
```javascript
527
import {
528
startKoin,
529
stopKoin,
530
GlobalContext,
531
KoinApplicationAlreadyStartedException,
532
IllegalStateException
533
} from "koin-core";
534
535
class ApplicationLifecycle {
536
constructor() {
537
this.isInitialized = false;
538
}
539
540
async start() {
541
try {
542
if (this.isInitialized) {
543
console.log("Application already initialized");
544
return;
545
}
546
547
startKoin((app) => {
548
app.modules([coreModule, apiModule]);
549
app.printLogger();
550
});
551
552
this.isInitialized = true;
553
console.log("Application started successfully");
554
555
} catch (error) {
556
if (error instanceof KoinApplicationAlreadyStartedException) {
557
console.warn("Koin application already started, skipping initialization");
558
this.isInitialized = true;
559
} else {
560
console.error("Failed to start application:", error.message);
561
throw error;
562
}
563
}
564
}
565
566
async stop() {
567
try {
568
if (!this.isInitialized) {
569
console.log("Application not initialized, nothing to stop");
570
return;
571
}
572
573
stopKoin();
574
this.isInitialized = false;
575
console.log("Application stopped successfully");
576
577
} catch (error) {
578
console.error("Error stopping application:", error.message);
579
// Force cleanup
580
this.isInitialized = false;
581
throw error;
582
}
583
}
584
585
getService(serviceName) {
586
try {
587
if (!this.isInitialized) {
588
throw new IllegalStateException("Application not initialized");
589
}
590
591
const koin = GlobalContext.get();
592
if (!koin) {
593
throw new IllegalStateException("Koin container not available");
594
}
595
596
return koin.get(named(serviceName));
597
598
} catch (error) {
599
if (error instanceof IllegalStateException) {
600
console.error(`Illegal state: ${error.message}`);
601
throw new Error("Service not available - application not ready");
602
}
603
throw error;
604
}
605
}
606
}
607
```
608
609
### Error Recovery and Fallback Strategies
610
611
Implement recovery strategies for robust error handling.
612
613
```javascript { .api }
614
/**
615
* Error recovery utility for dependency injection failures
616
*/
617
class DependencyRecovery {
618
static createFallbackStrategy(primaryFactory, fallbackFactory) {
619
return (scope, params) => {
620
try {
621
return primaryFactory(scope, params);
622
} catch (error) {
623
console.warn("Primary factory failed, using fallback:", error.message);
624
return fallbackFactory(scope, params);
625
}
626
};
627
}
628
629
static createRetryStrategy(factory, maxRetries = 3, delay = 1000) {
630
return async (scope, params) => {
631
for (let attempt = 1; attempt <= maxRetries; attempt++) {
632
try {
633
return await factory(scope, params);
634
} catch (error) {
635
if (attempt === maxRetries) {
636
throw error;
637
}
638
console.warn(`Attempt ${attempt} failed, retrying in ${delay}ms:`, error.message);
639
await new Promise(resolve => setTimeout(resolve, delay));
640
}
641
}
642
};
643
}
644
}
645
```
646
647
**Usage Examples:**
648
649
```javascript
650
import { module, DependencyRecovery } from "koin-core";
651
652
const resilientModule = module((builder) => {
653
// Service with fallback strategy
654
builder.single(
655
DependencyRecovery.createFallbackStrategy(
656
(scope, params) => new PrimaryDatabaseService(),
657
(scope, params) => new FallbackDatabaseService()
658
)
659
);
660
661
// Service with retry strategy
662
builder.factory(
663
DependencyRecovery.createRetryStrategy(
664
async (scope, params) => new ExternalApiClient(),
665
3, // max retries
666
2000 // delay between retries
667
)
668
);
669
});
670
```
671
672
## Types
673
674
```javascript { .api }
675
/** Base error types for Koin dependency injection */
676
677
/** Definition and resolution errors */
678
class NoDefinitionFoundException extends Error {
679
qualifier?: Qualifier;
680
type?: any;
681
}
682
683
class DefinitionOverrideException extends Error {
684
definition?: BeanDefinition<any>;
685
}
686
687
class InstanceCreationException extends Error {
688
cause?: Error;
689
definition?: BeanDefinition<any>;
690
}
691
692
/** Scope-related errors */
693
class ClosedScopeException extends Error {
694
scopeId: string;
695
}
696
697
class ScopeNotCreatedException extends Error {
698
scopeId: string;
699
}
700
701
class ScopeAlreadyCreatedException extends Error {
702
scopeId: string;
703
}
704
705
class NoScopeDefFoundException extends Error {
706
scopeQualifier?: Qualifier;
707
}
708
709
class MissingScopeValueException extends Error {}
710
711
/** Parameter and property errors */
712
class NoParameterFoundException extends Error {
713
parameterIndex?: number;
714
parameterType?: any;
715
}
716
717
class DefinitionParameterException extends Error {
718
definition?: BeanDefinition<any>;
719
}
720
721
class MissingPropertyException extends Error {
722
key: string;
723
}
724
725
class NoPropertyFileFoundException extends Error {
726
filePath?: string;
727
}
728
729
/** Application state errors */
730
class KoinApplicationAlreadyStartedException extends Error {}
731
732
class IllegalStateException extends Error {}
733
```