or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

arguments.mdconfiguration-sources.mdcore-commands.mdexceptions.mdindex.mdoptions.mdparameter-groups.mdparameter-types.mdshell-completion.mdtesting-utilities.md

exceptions.mddocs/

0

# Exceptions

1

2

Exception classes for command line processing errors and program flow control. Clikt provides a comprehensive set of exceptions that are automatically caught and formatted when using `CliktCommand.main()`.

3

4

## Capabilities

5

6

### Base Exception Classes

7

8

Core exception hierarchy for CLI error handling.

9

10

```kotlin { .api }

11

/**

12

* Base exception for command line processing errors

13

* @param message Error message

14

* @param cause Underlying cause

15

* @param statusCode Exit code (default 1)

16

* @param printError Whether to print to stderr (default true)

17

*/

18

open class CliktError(

19

message: String? = null,

20

cause: Exception? = null,

21

val statusCode: Int = 1,

22

val printError: Boolean = true

23

) : RuntimeException(message, cause)

24

25

/**

26

* Interface for CliktErrors that have a context attached

27

*/

28

interface ContextCliktError {

29

/** The context of the command that raised this error */

30

var context: Context?

31

}

32

33

/**

34

* Base class for user errors

35

* @param message Error message

36

* @param paramName Parameter name that caused the error

37

* @param statusCode Exit code (default 1)

38

*/

39

open class UsageError(

40

message: String?,

41

var paramName: String? = null,

42

statusCode: Int = 1

43

) : CliktError(message, statusCode = statusCode), ContextCliktError {

44

45

constructor(message: String, argument: Argument, statusCode: Int = 1)

46

constructor(message: String, option: Option, statusCode: Int = 1)

47

constructor(argument: Argument, statusCode: Int = 1)

48

constructor(option: Option, statusCode: Int = 1)

49

50

/** Format the error message for display */

51

open fun formatMessage(localization: Localization, formatter: ParameterFormatter): String

52

53

override var context: Context?

54

}

55

```

56

57

### Program Control Exceptions

58

59

Exceptions used to control program flow and output.

60

61

```kotlin { .api }

62

/**

63

* Exception that indicates the command's help should be printed

64

* @param context Command context

65

* @param error Whether to print to stderr (default false)

66

* @param statusCode Exit code (default 0)

67

*/

68

class PrintHelpMessage(

69

override var context: Context?,

70

val error: Boolean = false,

71

statusCode: Int = 0

72

) : CliktError(printError = false, statusCode = statusCode), ContextCliktError

73

74

/**

75

* Exception that indicates a message should be printed

76

* @param message Message to print

77

* @param statusCode Exit code (default 0)

78

* @param printError Whether to print to stderr (default false)

79

*/

80

open class PrintMessage(

81

message: String,

82

statusCode: Int = 0,

83

printError: Boolean = false

84

) : CliktError(message, statusCode = statusCode, printError = printError)

85

86

/**

87

* Indicate that the program finished in a controlled manner

88

* @param statusCode Exit code

89

*/

90

open class ProgramResult(statusCode: Int) : CliktError(statusCode = statusCode)

91

92

/**

93

* Internal error that signals Clikt to abort

94

*/

95

class Abort : ProgramResult(statusCode = 1)

96

97

/**

98

* Exception that indicates shell completion code should be printed

99

*/

100

class PrintCompletionMessage(message: String) : PrintMessage(message, statusCode = 0)

101

```

102

103

### Parameter Error Exceptions

104

105

Specific exceptions for parameter validation and parsing errors.

106

107

```kotlin { .api }

108

/**

109

* Multiple usage errors occurred

110

* @param errors List of usage errors

111

*/

112

class MultiUsageError(

113

val errors: List<UsageError>

114

) : UsageError(null, statusCode = errors.first().statusCode) {

115

116

companion object {

117

/** Build MultiUsageError from error list, or return single error/null */

118

fun buildOrNull(errors: List<UsageError>): UsageError?

119

}

120

121

override fun formatMessage(localization: Localization, formatter: ParameterFormatter): String

122

}

123

124

/**

125

* A parameter was given invalid format or type

126

*/

127

class BadParameterValue : UsageError {

128

constructor(message: String)

129

constructor(message: String, argument: Argument)

130

constructor(message: String, option: Option)

131

constructor(message: String, option: Option, name: String)

132

133

override fun formatMessage(localization: Localization, formatter: ParameterFormatter): String

134

}

135

136

/**

137

* A required option was not provided

138

* @param option The missing option

139

*/

140

class MissingOption(option: Option) : UsageError(option) {

141

override fun formatMessage(localization: Localization, formatter: ParameterFormatter): String

142

}

143

144

/**

145

* A required argument was not provided

146

* @param argument The missing argument

147

*/

148

class MissingArgument(argument: Argument) : UsageError(argument) {

149

override fun formatMessage(localization: Localization, formatter: ParameterFormatter): String

150

}

151

152

/**

153

* A subcommand was provided that does not exist

154

* @param paramName The invalid subcommand name

155

* @param possibilities List of valid subcommand names

156

*/

157

class NoSuchSubcommand(

158

paramName: String,

159

private val possibilities: List<String> = emptyList()

160

) : UsageError(null, paramName) {

161

override fun formatMessage(localization: Localization, formatter: ParameterFormatter): String

162

}

163

164

/**

165

* An option was provided that does not exist

166

* @param paramName The invalid option name

167

* @param possibilities List of valid option names

168

*/

169

class NoSuchOption(

170

paramName: String,

171

private val possibilities: List<String> = emptyList()

172

) : UsageError(null, paramName) {

173

override fun formatMessage(localization: Localization, formatter: ParameterFormatter): String

174

}

175

176

/**

177

* An option was supplied with incorrect number of values

178

* @param minValues Expected minimum number of values

179

* @param paramName The option name

180

*/

181

class IncorrectOptionValueCount(

182

private val minValues: Int,

183

paramName: String

184

) : UsageError(null, paramName) {

185

186

constructor(option: Option, paramName: String)

187

188

override fun formatMessage(localization: Localization, formatter: ParameterFormatter): String

189

}

190

191

/**

192

* An argument was supplied with incorrect number of values

193

* @param nvalues Expected number of values

194

* @param argument The argument

195

*/

196

class IncorrectArgumentValueCount(

197

val nvalues: Int,

198

argument: Argument

199

) : UsageError(argument) {

200

201

constructor(argument: Argument)

202

203

override fun formatMessage(localization: Localization, formatter: ParameterFormatter): String

204

}

205

206

/**

207

* Multiple mutually exclusive options were supplied

208

* @param names List of conflicting option names

209

*/

210

class MutuallyExclusiveGroupException(

211

val names: List<String>

212

) : UsageError(null) {

213

override fun formatMessage(localization: Localization, formatter: ParameterFormatter): String

214

}

215

```

216

217

### File and Configuration Exceptions

218

219

Exceptions related to file processing and configuration.

220

221

```kotlin { .api }

222

/**

223

* A required configuration file was not found

224

* @param filename The missing file name

225

*/

226

class FileNotFound(

227

val filename: String

228

) : UsageError(null) {

229

override fun formatMessage(localization: Localization, formatter: ParameterFormatter): String

230

}

231

232

/**

233

* A configuration file failed to parse correctly

234

* @param filename The file that failed to parse

235

* @param message Error description

236

* @param lineno Optional line number where error occurred

237

*/

238

class InvalidFileFormat(

239

private val filename: String,

240

message: String,

241

private val lineno: Int? = null

242

) : UsageError(message) {

243

override fun formatMessage(localization: Localization, formatter: ParameterFormatter): String

244

}

245

```

246

247

## Usage Examples

248

249

### Basic Error Handling

250

251

```kotlin

252

import com.github.ajalt.clikt.core.*

253

import com.github.ajalt.clikt.parameters.options.*

254

import com.github.ajalt.clikt.parameters.arguments.*

255

256

class MyCommand : CliktCommand() {

257

private val file by argument(help = "Input file")

258

private val count by option("--count", "-c", help = "Number of items").int()

259

260

override fun run() {

261

// Throw custom error

262

if (!File(file).exists()) {

263

throw UsageError("File not found: $file")

264

}

265

266

// Validation with context

267

count?.let { c ->

268

if (c <= 0) {

269

throw BadParameterValue("Count must be positive", ::count.option)

270

}

271

}

272

}

273

}

274

275

fun main(args: Array<String>) {

276

try {

277

MyCommand().main(args)

278

} catch (e: CliktError) {

279

// Custom error handling

280

println("Error: ${e.message}")

281

exitProcess(e.statusCode)

282

}

283

}

284

```

285

286

### Program Flow Control

287

288

```kotlin

289

class VersionCommand : CliktCommand() {

290

private val version by option("--version", help = "Show version").flag()

291

292

override fun run() {

293

if (version) {

294

// Print version and exit successfully

295

throw PrintMessage("MyApp version 1.0.0")

296

}

297

}

298

}

299

300

class AbortCommand : CliktCommand() {

301

private val dangerous by option("--dangerous", help = "Dangerous operation").flag()

302

303

override fun run() {

304

if (dangerous && !confirmDangerous()) {

305

// Abort without error message

306

throw Abort()

307

}

308

}

309

310

private fun confirmDangerous(): Boolean {

311

echo("This is a dangerous operation. Are you sure? (y/N)")

312

return readLine()?.lowercase() == "y"

313

}

314

}

315

```

316

317

### Custom Validation Errors

318

319

```kotlin

320

class DatabaseCommand : CliktCommand() {

321

private val host by option("--host", help = "Database host").required()

322

private val port by option("--port", help = "Database port").int().default(5432)

323

324

override fun run() {

325

// Custom validation with proper error reporting

326

if (port !in 1..65535) {

327

throw BadParameterValue(

328

"Port must be between 1 and 65535, got $port",

329

::port.option

330

)

331

}

332

333

try {

334

connectToDatabase(host, port)

335

} catch (e: SQLException) {

336

throw UsageError("Failed to connect to database: ${e.message}")

337

}

338

}

339

}

340

```

341

342

### Multiple Error Handling

343

344

```kotlin

345

class ValidateCommand : CliktCommand() {

346

private val files by argument(help = "Files to validate").multiple()

347

348

override fun run() {

349

val errors = mutableListOf<UsageError>()

350

351

for (file in files) {

352

try {

353

validateFile(file)

354

} catch (e: Exception) {

355

errors.add(BadParameterValue("Invalid file $file: ${e.message}"))

356

}

357

}

358

359

// Throw multiple errors at once

360

MultiUsageError.buildOrNull(errors)?.let { throw it }

361

362

echo("All files validated successfully")

363

}

364

}

365

```