interpretExitCode function
Provide a semantic interpretation of an exit code for a given command.
Implementation
String interpretExitCode(int exitCode, String command) {
if (exitCode == 0) return 'Success';
final exe = extractExecutable(command) ?? '';
// Command-specific overrides that conflict with signal range.
// git uses 128 as a "fatal git error" sentinel even though 128 normally
// means "killed by signal 0", so check it first.
if (exitCode == 128 && (exe == 'git' || exe == 'gh')) {
return 'Fatal git error';
}
// General signals.
if (exitCode >= 128) {
final signal = exitCode - 128;
final signalNames = <int, String>{
1: 'SIGHUP (hangup)',
2: 'SIGINT (interrupt / Ctrl+C)',
3: 'SIGQUIT (quit)',
6: 'SIGABRT (abort)',
9: 'SIGKILL (killed)',
11: 'SIGSEGV (segmentation fault)',
13: 'SIGPIPE (broken pipe)',
14: 'SIGALRM (alarm)',
15: 'SIGTERM (terminated)',
};
final name = signalNames[signal] ?? 'signal $signal';
return 'Killed by $name (exit code $exitCode)';
}
// Command-specific codes.
switch (exe) {
case 'grep':
case 'egrep':
case 'fgrep':
case 'rg':
case 'ag':
if (exitCode == 1) return 'No matches found';
if (exitCode == 2) return 'Syntax error or inaccessible file';
break;
case 'diff':
if (exitCode == 1) return 'Files differ';
if (exitCode == 2) {
return 'Trouble (missing file, permission denied, etc.)';
}
break;
case 'test':
case '[':
if (exitCode == 1) return 'Condition evaluated to false';
break;
case 'curl':
if (exitCode == 6) return 'Could not resolve host';
if (exitCode == 7) return 'Failed to connect';
if (exitCode == 22) return 'HTTP error (4xx or 5xx)';
if (exitCode == 28) return 'Operation timed out';
if (exitCode == 35) return 'SSL/TLS connection error';
if (exitCode == 56) return 'Failure in receiving network data';
break;
case 'wget':
if (exitCode == 1) return 'Generic error';
if (exitCode == 4) return 'Network failure';
if (exitCode == 8) return 'Server issued an error response';
break;
case 'ssh':
case 'scp':
if (exitCode == 255) return 'SSH connection failure';
break;
case 'git':
if (exitCode == 1) {
return 'Git operation failed (check output for details)';
}
if (exitCode == 128) return 'Fatal git error';
break;
case 'make':
if (exitCode == 2) return 'Make encountered errors';
break;
case 'gcc':
case 'g++':
case 'clang':
case 'clang++':
case 'rustc':
case 'javac':
case 'tsc':
if (exitCode == 1) return 'Compilation error';
break;
case 'python':
case 'python3':
case 'node':
case 'ruby':
case 'perl':
if (exitCode == 1) return 'Runtime error or unhandled exception';
if (exitCode == 2) return 'Misuse of command (invalid arguments)';
break;
case 'npm':
case 'yarn':
case 'pnpm':
if (exitCode == 1) return 'Operation failed (check output)';
break;
case 'docker':
if (exitCode == 1) return 'Docker command failed';
if (exitCode == 125) return 'Docker daemon error';
if (exitCode == 126) {
return 'Command cannot be invoked (permission issue)';
}
if (exitCode == 127) return 'Command not found in container';
break;
}
// Generic interpretations.
switch (exitCode) {
case 1:
return 'General error';
case 2:
return 'Misuse of shell command (invalid arguments or syntax)';
case 126:
return 'Command found but not executable (permission denied)';
case 127:
return 'Command not found';
default:
return 'Non-zero exit code: $exitCode';
}
}