diff --git a/src/cli/KompanionApp.cpp b/src/cli/KompanionApp.cpp
index 6a79650..c5aedbf 100644
--- a/src/cli/KompanionApp.cpp
+++ b/src/cli/KompanionApp.cpp
@@ -133,13 +133,17 @@ void writeDsnToConfig(const std::string& dsn) {
 #endif
 }
 
-std::string readFileUtf8(const QString& path) {
+bool readFileUtf8(const QString& path, std::string& out, QString* error) {
   QFile file(path);
   if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
-    throw std::runtime_error(QString("Unable to open request file: %1").arg(path).toStdString());
+    if (error) {
+      *error = QStringLiteral("Unable to open request file: %1").arg(path);
+    }
+    return false;
   }
   const QByteArray data = file.readAll();
-  return QString::fromUtf8(data).toStdString();
+  out = QString::fromUtf8(data).toStdString();
+  return true;
 }
 
 bool looksLikeFile(const QString& value) {
@@ -307,13 +311,20 @@ bool testConnection(const std::string& dsn, QString* error = nullptr) {
   return opened;
 }
 
-bool schemaExists(QSqlDatabase& db) {
+bool schemaExists(QSqlDatabase& db, bool* exists, QString* error) {
   QSqlQuery query(db);
   if (!query.exec(QStringLiteral("SELECT EXISTS (SELECT 1 FROM pg_tables WHERE schemaname='public' AND tablename='memory_items')"))) {
-    throw std::runtime_error(query.lastError().text().toStdString());
+    if (error) {
+      *error = query.lastError().text();
+    }
+    return false;
   }
-  if (!query.next()) return false;
-  return query.value(0).toBool();
+  if (!query.next()) {
+    if (exists) *exists = false;
+    return true;
+  }
+  if (exists) *exists = query.value(0).toBool();
+  return true;
 }
 
 bool applySchemaFiles(QSqlDatabase& db,
@@ -380,29 +391,48 @@ bool ensureSchema(const std::string& dsn,
     return false;
   }
 
-  bool success = false;
-  try {
-    if (schemaExists(db)) {
-      if (verbose) out << "Schema already present.\n";
-      success = true;
+  bool exists = false;
+  QString err;
+  if (!schemaExists(db, &exists, &err)) {
+    out << "Failed to check schema: " << err << "\n";
+    db.close();
+    db = QSqlDatabase();
+    QSqlDatabase::removeDatabase(connName);
+    return false;
+  }
+
+  if (exists) {
+    if (verbose) out << "Schema already present.\n";
+    db.close();
+    db = QSqlDatabase();
+    QSqlDatabase::removeDatabase(connName);
+    return true;
+  }
+
+  out << "Schema not found; applying migrations...\n";
+  if (!applySchemaFiles(db, out, verbose)) {
+    out << "Schema application reported errors.\n";
+    db.close();
+    db = QSqlDatabase();
+    QSqlDatabase::removeDatabase(connName);
+    return false;
+  }
+
+  if (!schemaExists(db, &exists, &err) || !exists) {
+    out << "Schema still missing after applying migrations.\n";
+    if (!err.isEmpty()) {
+      out << "Last error: " << err << "\n";
     }
-    if (!success) {
-      out << "Schema not found; applying migrations...\n";
-      if (applySchemaFiles(db, out, verbose) && schemaExists(db)) {
-        out << "Schema initialized successfully.\n";
-        success = true;
-      } else {
-        out << "Schema still missing after applying migrations.\n";
-        success = false;
-      }
-    }
-  } catch (const std::exception& ex) {
-    out << "Failed to ensure schema: " << ex.what() << "\n";
+    db.close();
+    db = QSqlDatabase();
+    QSqlDatabase::removeDatabase(connName);
+    return false;
   }
   db.close();
   db = QSqlDatabase();
   QSqlDatabase::removeDatabase(connName);
-  return success;
+  out << "Schema initialized successfully.\n";
+  return true;
 }
 
 std::optional<std::string> autoDetectDsn() {
@@ -578,50 +608,54 @@ int runInteractiveSession(KomMcpServer& server,
       out.flush();
     }
 
-    try {
-      const std::string response = server.dispatch(toolName, payload);
-      if (verbose) {
-        out << "[response] " << QString::fromStdString(response) << "\n";
-      } else {
-        out << QString::fromStdString(response) << "\n";
-      }
-    } catch (const std::exception& ex) {
-      out << "Error: " << ex.what() << "\n";
+    const std::string response = server.dispatch(toolName, payload);
+    if (verbose) {
+      out << "[response] " << QString::fromStdString(response) << "\n";
+    } else {
+      out << QString::fromStdString(response) << "\n";
     }
   }
   return 0;
 }
-std::string resolveRequestPayload(const QCommandLineParser& parser,
-                                  const QStringList& positional,
-                                  const QCommandLineOption& requestOption,
-                                  const QCommandLineOption& stdinOption) {
+bool resolveRequestPayload(const QCommandLineParser& parser,
+                           const QStringList& positional,
+                           const QCommandLineOption& requestOption,
+                           const QCommandLineOption& stdinOption,
+                           std::string& payloadOut,
+                           QString* error) {
   if (parser.isSet(stdinOption)) {
-    return readAll(std::cin);
+    payloadOut = readAll(std::cin);
+    return true;
   }
 
   if (parser.isSet(requestOption)) {
     const QString arg = parser.value(requestOption);
     if (arg == "-" || parser.isSet(stdinOption)) {
-      return readAll(std::cin);
+      payloadOut = readAll(std::cin);
+      return true;
     }
     if (looksLikeFile(arg)) {
-      return readFileUtf8(arg);
+      return readFileUtf8(arg, payloadOut, error);
     }
-    return arg.toStdString();
+    payloadOut = arg.toStdString();
+    return true;
   }
 
   if (positional.size() > 1) {
     const QString arg = positional.at(1);
     if (arg == "-") {
-      return readAll(std::cin);
+      payloadOut = readAll(std::cin);
+      return true;
     }
     if (looksLikeFile(arg)) {
-      return readFileUtf8(arg);
+      return readFileUtf8(arg, payloadOut, error);
     }
-    return arg.toStdString();
+    payloadOut = arg.toStdString();
+    return true;
   }
 
-  return "{}";
+  payloadOut = "{}";
+  return true;
 }
 
 void printToolList(const KomMcpServer& server) {
@@ -749,25 +783,27 @@ int main(int argc, char** argv) {
   }
 
   std::string request;
-  try {
-    request = resolveRequestPayload(parser, positional, requestOption, stdinOption);
-  } catch (const std::exception& ex) {
-    std::cerr << "Error: " << ex.what() << "\n";
+  QString requestError;
+  if (!resolveRequestPayload(parser,
+                             positional,
+                             requestOption,
+                             stdinOption,
+                             request,
+                             &requestError)) {
+    const QString message = requestError.isEmpty()
+                                ? QStringLiteral("Failed to resolve request payload.")
+                                : requestError;
+    std::cerr << "Error: " << message.toStdString() << "\n";
     return 1;
   }
 
-  try {
-    if (verbose) {
-      std::cerr << "[request] " << request << "\n";
-    }
-    const std::string response = server.dispatch(toolName, request);
-    if (verbose) {
-      std::cerr << "[response] " << response << "\n";
-    }
-    std::cout << response << std::endl;
-    return 0;
-  } catch (const std::exception& ex) {
-    std::cerr << "Error: " << ex.what() << "\n";
+  if (verbose) {
+    std::cerr << "[request] " << request << "\n";
   }
-  return 1;
+  const std::string response = server.dispatch(toolName, request);
+  if (verbose) {
+    std::cerr << "[response] " << response << "\n";
+  }
+  std::cout << response << std::endl;
+  return 0;
 }
diff --git a/src/mcp/HandlersIntrospection.hpp b/src/mcp/HandlersIntrospection.hpp
index 3e41ae2..e5d02e3 100644
--- a/src/mcp/HandlersIntrospection.hpp
+++ b/src/mcp/HandlersIntrospection.hpp
@@ -74,7 +74,15 @@ inline std::string runCommandCapture(const char* cmd, std::size_t maxBytes = 819
     (void)maxBytes;
     return "git status capture not supported on this platform";
 #else
-    std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose);
+    struct PipeCloser {
+        void operator()(FILE* file) const noexcept {
+            if (file != nullptr) {
+                pclose(file);
+            }
+        }
+    };
+
+    std::unique_ptr<FILE, PipeCloser> pipe(popen(cmd, "r"), PipeCloser{});
     if (!pipe) {
         return "git status unavailable";
     }
