diff --git a/job.go b/job.go
index d6a6c54a76dedabb50a0e5da600683d26ecb65f0..0d15cee1167507ab7737e53fa7812434d6b9ebca 100644
--- a/job.go
+++ b/job.go
@@ -17,8 +17,9 @@ func (id JobID) String() string {
 	return string(id)
 }
 
-type GetResult interface {
+type GetResultAndError interface {
 	GetResult() string
+	GetError() (string, int)
 }
 
 // Priority is the priority of a job
@@ -206,6 +207,11 @@ func (j *Job[T]) Execute(ctx context.Context) (RunGenericResult, error) {
 	endTime := time.Now()
 	elapsedTime := endTime.Sub(startTime)
 
+	isSuccessful := runnerError == nil
+	if r.Status != ResultStatusSuccess {
+		isSuccessful = false
+	}
+
 	j.mu.Lock()
 	defer j.mu.Unlock()
 
@@ -235,8 +241,7 @@ func (j *Job[T]) Execute(ctx context.Context) (RunGenericResult, error) {
 		j.stats.TimeMetrics.AvgRunTime = j.stats.TimeMetrics.TotalRunTime / time.Duration(j.stats.RunCount)
 	}
 
-	// Update SuccessCount or ErrorCount and codes
-	if runnerError == nil {
+	if isSuccessful {
 		j.stats.SuccessCount++
 	} else {
 		j.stats.ErrorCount++
@@ -246,13 +251,23 @@ func (j *Job[T]) Execute(ctx context.Context) (RunGenericResult, error) {
 		StartTime: startTime,
 	}
 
-	if runnerError == nil {
+	if isSuccessful {
 		newLog.IsSuccessful = true
 		newLog.ExitCode = 0
 	} else {
+		switch v := any(r.Data).(type) {
+		case GetResultAndError:
+			newLog.ErrorMsg, newLog.ExitCode = v.GetError()
+		}
+
+		if newLog.ErrorMsg == "" {
+			newLog.ErrorMsg = runnerError.Error()
+		}
+
 		newLog.IsSuccessful = false
-		newLog.ExitCode = 1 // Set to appropriate error code if applicable
-		newLog.ErrorMsg = runnerError.Error()
+		if newLog.ExitCode == 0 {
+			newLog.ExitCode = DefaultErrorExitCode
+		}
 	}
 
 	newLog.StartTime = startTime
@@ -260,11 +275,11 @@ func (j *Job[T]) Execute(ctx context.Context) (RunGenericResult, error) {
 	newLog.ProcessID = os.Getpid() // Assuming you want the PID of the current process
 
 	newLog.EndTime = time.Now()
-	if runnerError != nil {
-		newLog.ErrorMsg = runnerError.Error()
-	}
 
-	newLog.Result = CheckAndCallGetResult(&r.Data)
+	switch v := any(r.Data).(type) {
+	case GetResultAndError:
+		newLog.Result = v.GetResult()
+	}
 
 	j.logs = append(j.logs, newLog)
 
@@ -272,14 +287,6 @@ func (j *Job[T]) Execute(ctx context.Context) (RunGenericResult, error) {
 	return genericResult, runnerError
 }
 
-func CheckAndCallGetResult[T any](data T) string {
-	switch v := any(data).(type) {
-	case GetResult:
-		return v.GetResult()
-	}
-	return ""
-}
-
 // Cancel cancels the job, currently a no-op
 func (j *Job[T]) Cancel() error {
 	return nil
diff --git a/licenses/github.com/fsnotify/fsnotify/LICENSE b/licenses/github.com/fsnotify/fsnotify/LICENSE
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/.github/CONTRIBUTING.md b/licenses/github.com/go-sql-driver/mysql/.github/CONTRIBUTING.md
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/.github/ISSUE_TEMPLATE.md b/licenses/github.com/go-sql-driver/mysql/.github/ISSUE_TEMPLATE.md
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/.github/PULL_REQUEST_TEMPLATE.md b/licenses/github.com/go-sql-driver/mysql/.github/PULL_REQUEST_TEMPLATE.md
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/.github/workflows/codeql.yml b/licenses/github.com/go-sql-driver/mysql/.github/workflows/codeql.yml
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/.github/workflows/test.yml b/licenses/github.com/go-sql-driver/mysql/.github/workflows/test.yml
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/.gitignore b/licenses/github.com/go-sql-driver/mysql/.gitignore
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/AUTHORS b/licenses/github.com/go-sql-driver/mysql/AUTHORS
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/CHANGELOG.md b/licenses/github.com/go-sql-driver/mysql/CHANGELOG.md
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/LICENSE b/licenses/github.com/go-sql-driver/mysql/LICENSE
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/README.md b/licenses/github.com/go-sql-driver/mysql/README.md
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/atomic_bool.go b/licenses/github.com/go-sql-driver/mysql/atomic_bool.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/atomic_bool_go118.go b/licenses/github.com/go-sql-driver/mysql/atomic_bool_go118.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/atomic_bool_test.go b/licenses/github.com/go-sql-driver/mysql/atomic_bool_test.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/auth.go b/licenses/github.com/go-sql-driver/mysql/auth.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/auth_test.go b/licenses/github.com/go-sql-driver/mysql/auth_test.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/benchmark_test.go b/licenses/github.com/go-sql-driver/mysql/benchmark_test.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/buffer.go b/licenses/github.com/go-sql-driver/mysql/buffer.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/collations.go b/licenses/github.com/go-sql-driver/mysql/collations.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/conncheck.go b/licenses/github.com/go-sql-driver/mysql/conncheck.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/conncheck_dummy.go b/licenses/github.com/go-sql-driver/mysql/conncheck_dummy.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/conncheck_test.go b/licenses/github.com/go-sql-driver/mysql/conncheck_test.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/connection.go b/licenses/github.com/go-sql-driver/mysql/connection.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/connection_test.go b/licenses/github.com/go-sql-driver/mysql/connection_test.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/connector.go b/licenses/github.com/go-sql-driver/mysql/connector.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/connector_test.go b/licenses/github.com/go-sql-driver/mysql/connector_test.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/const.go b/licenses/github.com/go-sql-driver/mysql/const.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/driver.go b/licenses/github.com/go-sql-driver/mysql/driver.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/driver_test.go b/licenses/github.com/go-sql-driver/mysql/driver_test.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/dsn.go b/licenses/github.com/go-sql-driver/mysql/dsn.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/dsn_test.go b/licenses/github.com/go-sql-driver/mysql/dsn_test.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/errors.go b/licenses/github.com/go-sql-driver/mysql/errors.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/errors_test.go b/licenses/github.com/go-sql-driver/mysql/errors_test.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/fields.go b/licenses/github.com/go-sql-driver/mysql/fields.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/fuzz.go b/licenses/github.com/go-sql-driver/mysql/fuzz.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/go.mod b/licenses/github.com/go-sql-driver/mysql/go.mod
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/infile.go b/licenses/github.com/go-sql-driver/mysql/infile.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/nulltime.go b/licenses/github.com/go-sql-driver/mysql/nulltime.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/nulltime_test.go b/licenses/github.com/go-sql-driver/mysql/nulltime_test.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/packets.go b/licenses/github.com/go-sql-driver/mysql/packets.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/packets_test.go b/licenses/github.com/go-sql-driver/mysql/packets_test.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/result.go b/licenses/github.com/go-sql-driver/mysql/result.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/rows.go b/licenses/github.com/go-sql-driver/mysql/rows.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/statement.go b/licenses/github.com/go-sql-driver/mysql/statement.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/statement_test.go b/licenses/github.com/go-sql-driver/mysql/statement_test.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/transaction.go b/licenses/github.com/go-sql-driver/mysql/transaction.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/utils.go b/licenses/github.com/go-sql-driver/mysql/utils.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/go-sql-driver/mysql/utils_test.go b/licenses/github.com/go-sql-driver/mysql/utils_test.go
old mode 100644
new mode 100755
diff --git a/licenses/github.com/google/uuid/LICENSE b/licenses/github.com/google/uuid/LICENSE
old mode 100644
new mode 100755
diff --git a/licenses/github.com/jinzhu/inflection/LICENSE b/licenses/github.com/jinzhu/inflection/LICENSE
old mode 100644
new mode 100755
diff --git a/licenses/github.com/jinzhu/now/License b/licenses/github.com/jinzhu/now/License
old mode 100644
new mode 100755
diff --git a/licenses/github.com/kr/fs/LICENSE b/licenses/github.com/kr/fs/LICENSE
old mode 100644
new mode 100755
diff --git a/licenses/github.com/pkg/sftp/LICENSE b/licenses/github.com/pkg/sftp/LICENSE
old mode 100644
new mode 100755
diff --git a/licenses/github.com/robfig/cron/v3/LICENSE b/licenses/github.com/robfig/cron/v3/LICENSE
old mode 100644
new mode 100755
diff --git a/licenses/github.com/shirou/gopsutil/v3/LICENSE b/licenses/github.com/shirou/gopsutil/v3/LICENSE
old mode 100644
new mode 100755
diff --git a/licenses/github.com/tklauser/go-sysconf/LICENSE b/licenses/github.com/tklauser/go-sysconf/LICENSE
old mode 100644
new mode 100755
diff --git a/licenses/github.com/tklauser/numcpus/LICENSE b/licenses/github.com/tklauser/numcpus/LICENSE
old mode 100644
new mode 100755
diff --git a/licenses/go.uber.org/multierr/LICENSE.txt b/licenses/go.uber.org/multierr/LICENSE.txt
old mode 100644
new mode 100755
diff --git a/licenses/go.uber.org/zap/LICENSE.txt b/licenses/go.uber.org/zap/LICENSE.txt
old mode 100644
new mode 100755
diff --git a/licenses/golang.org/x/crypto/LICENSE b/licenses/golang.org/x/crypto/LICENSE
old mode 100644
new mode 100755
diff --git a/licenses/golang.org/x/sys/unix/LICENSE b/licenses/golang.org/x/sys/unix/LICENSE
old mode 100644
new mode 100755
diff --git a/licenses/gopkg.in/yaml.v3/LICENSE b/licenses/gopkg.in/yaml.v3/LICENSE
old mode 100644
new mode 100755
diff --git a/licenses/gopkg.in/yaml.v3/NOTICE b/licenses/gopkg.in/yaml.v3/NOTICE
old mode 100644
new mode 100755
diff --git a/licenses/gorm.io/driver/mysql/License b/licenses/gorm.io/driver/mysql/License
old mode 100644
new mode 100755
diff --git a/licenses/gorm.io/gorm/LICENSE b/licenses/gorm.io/gorm/LICENSE
old mode 100644
new mode 100755
diff --git a/runnable-counter.go b/runnable-counter.go
index 2484da2afade245ea789238ab7b9f4a617dde53e..82c27b3ef6bfda06f6fcecf74e7623cef8efac86 100644
--- a/runnable-counter.go
+++ b/runnable-counter.go
@@ -31,6 +31,10 @@ func (c *CounterResult) GetResult() string {
 	return fmt.Sprintf("Count: %d", c.Count)
 }
 
+func (c *CounterResult) GetError() (string, int) {
+	return "", 0
+}
+
 // CounterRunnable is a runnable that counts
 type CounterRunnable struct {
 	Count int `json:"count" yaml:"count"`
diff --git a/runnable-fileoperation.go b/runnable-fileoperation.go
index 859a7e83578b35ae0db004af4ed25a331dc9f68e..9631fc84b212ef4db6ed97b11b6865929e93bb52 100644
--- a/runnable-fileoperation.go
+++ b/runnable-fileoperation.go
@@ -41,6 +41,13 @@ func (f *FileOperationResult) GetResult() string {
 	return f.Content
 }
 
+func (f *FileOperationResult) GetError() (string, int) {
+	if f.Success == false {
+		return "FileOperationResult failed", 1
+	}
+	return "", 0
+}
+
 const (
 	FileOperationRead   = "read"
 	FileOperationWrite  = "write"
diff --git a/runnable-gorm.go b/runnable-gorm.go
index 9aabc84172a19c31dc523db16c921fc72ee01646..8215f63e521387730f56cd702511f093f2835fb6 100644
--- a/runnable-gorm.go
+++ b/runnable-gorm.go
@@ -42,6 +42,10 @@ func (d *DBResult) GetResult() string {
 	return fmt.Sprintf("RowsAffected: %d", d.RowsAffected)
 }
 
+func (d *DBResult) GetError() (string, int) {
+	return "", 0
+}
+
 type DBRunnable struct {
 	Type  string
 	DSN   string
@@ -72,17 +76,24 @@ func (d *DBRunnable) Run(ctx context.Context) (RunResult[DBResult], error) {
 		case "mysql":
 			db, err = gorm.Open(mysql.Open(d.DSN), &gorm.Config{})
 		default:
-			return RunResult[DBResult]{Status: ResultStatusFailed}, ErrUnsupportedDatabaseType
+			return RunResult[DBResult]{Status: ResultStatusFailed,
+				Data: DBResult{},
+			}, ErrUnsupportedDatabaseType
 		}
 
 		if err != nil {
-			return RunResult[DBResult]{Status: ResultStatusFailed}, err
+			return RunResult[DBResult]{Status: ResultStatusFailed,
+					Data: DBResult{},
+				},
+				err
 		}
 	}
 
 	result := db.Exec(d.Query)
 	if result.Error != nil {
-		return RunResult[DBResult]{Status: ResultStatusFailed}, result.Error
+		return RunResult[DBResult]{Status: ResultStatusFailed,
+			Data: DBResult{},
+		}, result.Error
 	}
 
 	return RunResult[DBResult]{
diff --git a/runnable-http.go b/runnable-http.go
index 9f780bb71629739c610b833ae0bfd3136a70046d..8f3db274fc516f8870b881fd9f2df7da72dc3c79 100644
--- a/runnable-http.go
+++ b/runnable-http.go
@@ -50,6 +50,13 @@ func (h *HTTPResult) GetResult() string {
 	return fmt.Sprintf("StatusCode: %d\n\n%s", h.StatusCode, h.Body)
 }
 
+func (h *HTTPResult) GetError() (string, int) {
+	if h.StatusCode >= 400 {
+		return fmt.Sprintf("StatusCode: %d\n\n%s", h.StatusCode, h.Body), h.StatusCode
+	}
+	return "", 0
+}
+
 type HTTPRunnable struct {
 	URL    string
 	Method string
diff --git a/runnable-mail.go b/runnable-mail.go
index 5b27853b17c7b6e13e73bdd4ae06c24626a5ea0c..c94276331440335ac229a0b97916137351d1f857 100644
--- a/runnable-mail.go
+++ b/runnable-mail.go
@@ -79,6 +79,13 @@ func (m *MailResult) GetResult() string {
 	return fmt.Sprintf("Sent: %t\n\nServerReply: %s\n\nSmtpStatusCode: %d", m.Sent, m.ServerReply, m.SmtpStatusCode)
 }
 
+func (m *MailResult) GetError() (string, int) {
+	if !m.Sent {
+		return fmt.Sprintf("Sent: %t\n\nServerReply: %s\n\nSmtpStatusCode: %d", m.Sent, m.ServerReply, m.SmtpStatusCode), 1
+	}
+	return "", 0
+}
+
 type MailRunnable struct {
 	To       string
 	From     string
diff --git a/runnable-sftp.go b/runnable-sftp.go
index 86f9d9920da2d6fd556bd375a8535f1cfc630e5a..1226f3526f59004e9d229764f8bb2bc381bd3059 100644
--- a/runnable-sftp.go
+++ b/runnable-sftp.go
@@ -86,6 +86,10 @@ func (s *SFTPResult) GetResult() string {
 	return fmt.Sprintf("FilesCopied: %v", s.FilesCopied)
 }
 
+func (s *SFTPResult) GetError() (string, int) {
+	return "", 0
+}
+
 const (
 	CredentialTypePassword = "password"
 	CredentialTypeKey      = "key"
@@ -122,11 +126,14 @@ func (s *SFTPRunnable) Run(_ context.Context) (RunResult[SFTPResult], error) {
 	case CredentialTypeKey:
 		key, err := ssh.ParsePrivateKey([]byte(s.Credential))
 		if err != nil {
-			return RunResult[SFTPResult]{Status: ResultStatusFailed}, err
+			return RunResult[SFTPResult]{Status: ResultStatusFailed,
+				Data: SFTPResult{},
+			}, err
 		}
 		authMethod = ssh.PublicKeys(key)
 	default:
-		return RunResult[SFTPResult]{Status: ResultStatusFailed}, ErrUnsupportedCredentialType
+		return RunResult[SFTPResult]{Status: ResultStatusFailed,
+			Data: SFTPResult{}}, ErrUnsupportedCredentialType
 	}
 
 	var hkCallback ssh.HostKeyCallback
@@ -136,7 +143,9 @@ func (s *SFTPRunnable) Run(_ context.Context) (RunResult[SFTPResult], error) {
 		hostkeyBytes := []byte(s.HostKey)
 		hostKey, err := ssh.ParsePublicKey(hostkeyBytes)
 		if err != nil {
-			return RunResult[SFTPResult]{Status: ResultStatusFailed}, err
+			return RunResult[SFTPResult]{Status: ResultStatusFailed,
+				Data: SFTPResult{},
+			}, err
 		}
 
 		hkCallback = ssh.FixedHostKey(hostKey)
@@ -159,13 +168,17 @@ func (s *SFTPRunnable) Run(_ context.Context) (RunResult[SFTPResult], error) {
 
 	client, err := ssh.Dial("tcp", fmt.Sprintf("%s:%d", s.Host, s.Port), config)
 	if err != nil {
-		return RunResult[SFTPResult]{Status: ResultStatusFailed}, err
+		return RunResult[SFTPResult]{Status: ResultStatusFailed,
+			Data: SFTPResult{},
+		}, err
 	}
 	defer client.Close()
 
 	sftpClient, err := sftp.NewClient(client)
 	if err != nil {
-		return RunResult[SFTPResult]{Status: ResultStatusFailed}, err
+		return RunResult[SFTPResult]{Status: ResultStatusFailed,
+			Data: SFTPResult{},
+		}, err
 	}
 	defer sftpClient.Close()
 
@@ -177,7 +190,9 @@ func (s *SFTPRunnable) Run(_ context.Context) (RunResult[SFTPResult], error) {
 	case RemoteToLocal:
 		filesCopied, err = s.copyRemoteToLocal(sftpClient)
 	default:
-		return RunResult[SFTPResult]{Status: ResultStatusFailed}, ErrUnsupportedTransferDirection
+		return RunResult[SFTPResult]{Status: ResultStatusFailed,
+			Data: SFTPResult{},
+		}, ErrUnsupportedTransferDirection
 	}
 
 	if err != nil {
diff --git a/runnable-shell.go b/runnable-shell.go
index 444e52972c0ecb9b818e8e07b25fa3c8e4221b4b..dbe09f7650eb31893c9d7df81d77ffa14ab3df14 100644
--- a/runnable-shell.go
+++ b/runnable-shell.go
@@ -41,6 +41,13 @@ func (s *ShellResult) GetResult() string {
 	return s.Output
 }
 
+func (s *ShellResult) GetError() (string, int) {
+	if s.ExitCode != 0 {
+		return s.Error, s.ExitCode
+	}
+	return "", 0
+}
+
 type ShellRunnable struct {
 	ScriptPath string
 	Script     string