or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

access.mdexceptions.mdindex.mdloading.mdoptions.mdresolution.mdvalues.md

exceptions.mddocs/

0

# Exception Handling

1

2

Exception handling in Typesafe Config provides a comprehensive hierarchy of runtime exceptions for different error conditions. All exceptions extend ConfigException and provide detailed context information for debugging and error recovery.

3

4

## Exception Hierarchy

5

6

### ConfigException Base Class

7

8

Base class for all configuration-related exceptions.

9

10

```java { .api }

11

public abstract class ConfigException extends RuntimeException {

12

public ConfigException(String message);

13

public ConfigException(String message, Throwable cause);

14

public ConfigOrigin origin();

15

}

16

```

17

18

**Common Methods:**

19

- `getMessage()` - Human-readable error description

20

- `getCause()` - Underlying exception if applicable

21

- `origin()` - Configuration origin where error occurred

22

23

## Configuration Access Exceptions

24

25

### ConfigException.Missing

26

27

Thrown when a required configuration path is not found.

28

29

```java { .api }

30

public static class Missing extends ConfigException {

31

public String path();

32

}

33

```

34

35

**Usage Examples:**

36

37

```java

38

try {

39

String dbUrl = config.getString("database.url");

40

} catch (ConfigException.Missing e) {

41

String missingPath = e.path();

42

System.err.println("Missing required configuration: " + missingPath);

43

44

// Provide default or fail gracefully

45

String defaultUrl = "jdbc:h2:mem:default";

46

System.out.println("Using default database URL: " + defaultUrl);

47

}

48

```

49

50

### ConfigException.Null

51

52

Thrown when a configuration path exists but has a null value.

53

54

```java { .api }

55

public static class Null extends ConfigException.Missing {

56

// Inherits path() method from Missing

57

}

58

```

59

60

**Usage Examples:**

61

62

```java

63

try {

64

String apiKey = config.getString("api.key");

65

} catch (ConfigException.Null e) {

66

System.err.println("API key is explicitly set to null at: " + e.path());

67

// Handle null value scenario

68

} catch (ConfigException.Missing e) {

69

System.err.println("API key configuration is missing: " + e.path());

70

// Handle missing value scenario

71

}

72

```

73

74

### ConfigException.WrongType

75

76

Thrown when requesting a value with an incompatible type.

77

78

```java { .api }

79

public static class WrongType extends ConfigException {

80

public String path();

81

public ConfigValueType expected();

82

public ConfigValueType actual();

83

}

84

```

85

86

**Usage Examples:**

87

88

```java

89

try {

90

int port = config.getInt("server.port");

91

} catch (ConfigException.WrongType e) {

92

String path = e.path();

93

ConfigValueType expected = e.expected();

94

ConfigValueType actual = e.actual();

95

96

System.err.println(String.format(

97

"Type mismatch at %s: expected %s but got %s",

98

path, expected, actual

99

));

100

101

// Try alternative approaches

102

if (actual == ConfigValueType.STRING) {

103

try {

104

String portStr = config.getString(path);

105

int port = Integer.parseInt(portStr);

106

// Use parsed value

107

} catch (NumberFormatException nfe) {

108

// Handle invalid string format

109

}

110

}

111

}

112

```

113

114

## Parsing Exceptions

115

116

### ConfigException.Parse

117

118

Thrown when configuration files contain syntax errors.

119

120

```java { .api }

121

public static class Parse extends ConfigException {

122

public ConfigOrigin origin();

123

}

124

```

125

126

**Usage Examples:**

127

128

```java

129

try {

130

Config config = ConfigFactory.parseFile(configFile);

131

} catch (ConfigException.Parse e) {

132

ConfigOrigin origin = e.origin();

133

System.err.println(String.format(

134

"Parse error in %s at line %d: %s",

135

origin.filename(),

136

origin.lineNumber(),

137

e.getMessage()

138

));

139

140

// Handle parse error - maybe use defaults

141

Config defaultConfig = ConfigFactory.parseResources("reference.conf");

142

}

143

```

144

145

### ConfigException.IO

146

147

Thrown for I/O related errors when loading configuration files.

148

149

```java { .api }

150

public static class IO extends ConfigException {

151

public ConfigOrigin origin();

152

}

153

```

154

155

**Usage Examples:**

156

157

```java

158

try {

159

Config config = ConfigFactory.parseFile(new File("/etc/myapp/config.conf"));

160

} catch (ConfigException.IO e) {

161

System.err.println("I/O error reading configuration: " + e.getMessage());

162

163

// Try alternative locations

164

try {

165

config = ConfigFactory.parseFile(new File("./config.conf"));

166

} catch (ConfigException.IO e2) {

167

// Fall back to classpath resource

168

config = ConfigFactory.parseResources("application.conf");

169

}

170

}

171

```

172

173

## Resolution Exceptions

174

175

### ConfigException.UnresolvedSubstitution

176

177

Thrown when substitutions cannot be resolved.

178

179

```java { .api }

180

public static class UnresolvedSubstitution extends ConfigException {

181

public String path();

182

public String detail();

183

}

184

```

185

186

**Usage Examples:**

187

188

```java

189

try {

190

Config resolved = config.resolve();

191

} catch (ConfigException.UnresolvedSubstitution e) {

192

String path = e.path();

193

String detail = e.detail();

194

195

System.err.println(String.format(

196

"Cannot resolve substitution ${%s}: %s", path, detail

197

));

198

199

// Option 1: Allow partial resolution

200

Config partiallyResolved = config.resolve(

201

ConfigResolveOptions.defaults().setAllowUnresolved(true)

202

);

203

204

// Option 2: Provide missing values

205

Config withDefaults = config.withFallback(

206

ConfigFactory.parseString(path + " = \"default-value\"")

207

).resolve();

208

}

209

```

210

211

### ConfigException.NotResolved

212

213

Thrown when trying to access values from an unresolved configuration.

214

215

```java { .api }

216

public static class NotResolved extends ConfigException {

217

// Standard exception methods

218

}

219

```

220

221

**Usage Examples:**

222

223

```java

224

Config config = ConfigFactory.parseString("value = ${missing.ref}");

225

226

try {

227

// This will fail because config is not resolved

228

String value = config.getString("value");

229

} catch (ConfigException.NotResolved e) {

230

System.err.println("Configuration must be resolved first: " + e.getMessage());

231

232

// Resolve first

233

try {

234

Config resolved = config.resolve();

235

String value = resolved.getString("value");

236

} catch (ConfigException.UnresolvedSubstitution ue) {

237

// Handle unresolved substitutions

238

}

239

}

240

```

241

242

## Validation Exceptions

243

244

### ConfigException.ValidationFailed

245

246

Thrown by the `checkValid()` method when validation fails.

247

248

```java { .api }

249

public static class ValidationFailed extends ConfigException {

250

public Iterable<ValidationProblem> problems();

251

252

public static class ValidationProblem {

253

public String path();

254

public String problem();

255

public ConfigOrigin origin();

256

}

257

}

258

```

259

260

**Usage Examples:**

261

262

```java

263

Config reference = ConfigFactory.parseResources("reference.conf");

264

Config config = ConfigFactory.load();

265

266

try {

267

config.checkValid(reference);

268

} catch (ConfigException.ValidationFailed e) {

269

System.err.println("Configuration validation failed:");

270

271

for (ConfigException.ValidationProblem problem : e.problems()) {

272

String path = problem.path();

273

String description = problem.problem();

274

ConfigOrigin origin = problem.origin();

275

276

System.err.println(String.format(

277

" %s: %s (from %s:%d)",

278

path, description,

279

origin.filename(), origin.lineNumber()

280

));

281

}

282

283

// Handle validation failures

284

System.exit(1);

285

}

286

```

287

288

## Value-Specific Exceptions

289

290

### ConfigException.BadValue

291

292

Thrown when a configuration value is invalid for its intended use.

293

294

```java { .api }

295

public static class BadValue extends ConfigException {

296

public String path();

297

public String detail();

298

}

299

```

300

301

**Usage Examples:**

302

303

```java

304

try {

305

Duration timeout = config.getDuration("timeout");

306

} catch (ConfigException.BadValue e) {

307

System.err.println(String.format(

308

"Invalid duration value at %s: %s",

309

e.path(), e.detail()

310

));

311

312

// Use default duration

313

Duration defaultTimeout = Duration.ofSeconds(30);

314

}

315

316

try {

317

ConfigMemorySize heapSize = config.getMemorySize("jvm.heap");

318

} catch (ConfigException.BadValue e) {

319

System.err.println(String.format(

320

"Invalid memory size at %s: %s",

321

e.path(), e.detail()

322

));

323

}

324

```

325

326

### ConfigException.BadPath

327

328

Thrown when a path expression is malformed.

329

330

```java { .api }

331

public static class BadPath extends ConfigException {

332

public String path();

333

public String detail();

334

}

335

```

336

337

**Usage Examples:**

338

339

```java

340

try {

341

// Invalid path with special characters

342

boolean value = config.getBoolean("invalid..path");

343

} catch (ConfigException.BadPath e) {

344

System.err.println(String.format(

345

"Invalid path expression '%s': %s",

346

e.path(), e.detail()

347

));

348

349

// Use quoted path or fix the path

350

String quotedPath = ConfigUtil.joinPath("invalid", "", "path");

351

boolean value = config.getBoolean(quotedPath);

352

}

353

```

354

355

## JavaBean Exceptions

356

357

### ConfigException.BadBean

358

359

Thrown by ConfigBeanFactory when JavaBean creation fails.

360

361

```java { .api }

362

public static class BadBean extends ConfigException {

363

// Standard exception methods

364

}

365

```

366

367

**Usage Examples:**

368

369

```java

370

public class DatabaseConfig {

371

private String host;

372

private int port;

373

// getters and setters...

374

}

375

376

try {

377

DatabaseConfig dbConfig = ConfigBeanFactory.create(

378

config.getConfig("database"),

379

DatabaseConfig.class

380

);

381

} catch (ConfigException.BadBean e) {

382

System.err.println("Failed to create DatabaseConfig bean: " + e.getMessage());

383

384

// Manual configuration extraction

385

DatabaseConfig dbConfig = new DatabaseConfig();

386

dbConfig.setHost(config.getString("database.host"));

387

dbConfig.setPort(config.getInt("database.port"));

388

}

389

```

390

391

## Internal Exceptions

392

393

### ConfigException.BugOrBroken

394

395

Thrown for internal library errors that indicate bugs.

396

397

```java { .api }

398

public static class BugOrBroken extends ConfigException {

399

// Standard exception methods

400

}

401

```

402

403

**Usage:**

404

This exception indicates a bug in the Config library itself. If encountered, it should be reported to the library maintainers.

405

406

### ConfigException.Generic

407

408

Generic exception for miscellaneous error conditions.

409

410

```java { .api }

411

public static class Generic extends ConfigException {

412

// Standard exception methods

413

}

414

```

415

416

## Exception Handling Patterns

417

418

### Graceful Degradation

419

420

Handle configuration errors while maintaining application functionality.

421

422

```java

423

public class ConfigService {

424

private final Config config;

425

426

public ConfigService() {

427

Config primaryConfig = null;

428

429

try {

430

// Try primary configuration source

431

primaryConfig = ConfigFactory.load("application.conf");

432

} catch (ConfigException.IO e) {

433

System.err.println("Primary config not found, trying backup");

434

try {

435

primaryConfig = ConfigFactory.load("backup.conf");

436

} catch (ConfigException e2) {

437

System.err.println("Backup config failed, using defaults");

438

primaryConfig = ConfigFactory.parseResources("reference.conf");

439

}

440

}

441

442

this.config = primaryConfig;

443

}

444

445

public String getStringWithDefault(String path, String defaultValue) {

446

try {

447

return config.getString(path);

448

} catch (ConfigException.Missing | ConfigException.WrongType e) {

449

System.err.println("Using default for " + path + ": " + e.getMessage());

450

return defaultValue;

451

}

452

}

453

}

454

```

455

456

### Error Recovery

457

458

Implement recovery strategies for different exception types.

459

460

```java

461

public Config loadConfigWithRecovery(String resourceName) {

462

try {

463

return ConfigFactory.load(resourceName).resolve();

464

} catch (ConfigException.Parse e) {

465

// Parse error - try alternative formats

466

System.err.println("Parse error, trying JSON format: " + e.getMessage());

467

return ConfigFactory.parseResources(resourceName + ".json")

468

.resolve();

469

} catch (ConfigException.UnresolvedSubstitution e) {

470

// Resolution error - provide fallbacks

471

System.err.println("Resolution error, using partial config: " + e.getMessage());

472

return ConfigFactory.load(resourceName)

473

.resolve(ConfigResolveOptions.defaults().setAllowUnresolved(true));

474

} catch (ConfigException.IO e) {

475

// I/O error - use embedded defaults

476

System.err.println("I/O error, using embedded config: " + e.getMessage());

477

return ConfigFactory.parseResources("reference.conf").resolve();

478

}

479

}

480

```

481

482

### Validation and Error Reporting

483

484

Comprehensive error reporting for configuration issues.

485

486

```java

487

public void validateConfiguration(Config config) throws ConfigException {

488

List<String> errors = new ArrayList<>();

489

490

// Check required paths

491

String[] requiredPaths = {

492

"database.url", "database.username", "server.port"

493

};

494

495

for (String path : requiredPaths) {

496

try {

497

if (!config.hasPath(path)) {

498

errors.add("Missing required configuration: " + path);

499

} else if (config.getIsNull(path)) {

500

errors.add("Required configuration is null: " + path);

501

}

502

} catch (ConfigException e) {

503

errors.add("Error checking " + path + ": " + e.getMessage());

504

}

505

}

506

507

// Check value types and ranges

508

try {

509

int port = config.getInt("server.port");

510

if (port < 1 || port > 65535) {

511

errors.add("Server port must be between 1 and 65535, got: " + port);

512

}

513

} catch (ConfigException.Missing e) {

514

// Already handled above

515

} catch (ConfigException.WrongType e) {

516

errors.add("Server port must be a number: " + e.getMessage());

517

}

518

519

if (!errors.isEmpty()) {

520

String message = "Configuration validation failed:\n" +

521

String.join("\n", errors);

522

throw new ConfigException.Generic(message);

523

}

524

}

525

```

526

527

## Best Practices

528

529

1. **Catch specific exceptions**: Handle different ConfigException subtypes appropriately

530

2. **Provide meaningful defaults**: Have fallback values for optional configuration

531

3. **Log error details**: Include path, origin, and context information in error messages

532

4. **Validate early**: Check configuration validity at application startup

533

5. **Fail fast for critical errors**: Don't continue with invalid critical configuration

534

6. **Use graceful degradation**: Provide reduced functionality when possible

535

7. **Report configuration errors clearly**: Help users understand and fix configuration issues

536

8. **Test error scenarios**: Verify that your error handling works correctly