Fork me on GitHub

Is there any way to get detail data from query errors besides parsing the error message string? From something like this:

Execution error (PSQLException) at org.postgresql.core.v3.QueryExecutorImpl/receiveErrorResponse (
ERROR: duplicate key value violates unique constraint "..."
  Detail: Key (x)=(y) already exists.


The underlying SQLException doesn't give you much access/leverage: It's possible some vendor-specific exceptions under the hood might give you more convenient details but you've have to look at their docs. In general, calling bean (or's equivalent -- since it's a dependency of next.jdbc) on an exception might get you some of the way.


@U04V70XH6 are there some idiomatic/common approaches to error handling with next-jdbc, given these underlying limitations? Does it come down to catching high-level exceptions and interpreting them within their context to re-throw something with more application-specific error detail?


I don't think there's much difference between error handling around next.jdbc` and the broader picture in Clojure with exceptions, with a couple of notable specifics such as "expecting" an INSERT to fail with a constraint violation (`SQLIntegrityConstraintViolationException`) where you might want to catch a more specific exception and retry or perform some other action.


Thanks @U04V70XH6. I'll take some time to study the class hierarchy. SQLIntegrityConstraintViolationException is a helpful pointer.


I know this is an old thread, but I saw that you’re working with Postgres, and it turns out the Postgres JDBC driver has pretty good programmatic access to error details, just not in a very clojure-friendly way. First, java.sql.SqlException has getSQLState and getErrorCode methods. For the Postgres driver, one of those (I forget which) will contain the of the error. When we’ve needed to identify specific error causes e.g. to map to a domain-specific error type, we just add a mapping from the code to a more readable name in a big map in a util file. Second, PsqlException (the vendor-specific version of SqlException) has a .getServerErrorMessage method, which returns that has getters for all kinds of useful info: column name, constraint, table, internal position, etc. etc. We have a fn that just map-ifies the whole thing and re-throws it as an ex-info.

🙏 1

Thanks very much, @U01EB0V3H39. I'll have to look into those options next time I'm touching relevant code.


Since you're using next.jdbc, it depends on so you can probably use that to turn the exception object into a hash map since it will follow all the getters automatically for you...


@U04V70XH6 that works well. Here's a comparison of tapping the error message instance produced by (.getServerErrorMessage _e) and the hash-map version produced by j/from-java:

tap> #object[org.postgresql.util.ServerErrorMessage 0x16929fc0 "ERROR: relation \"repo\" already exists"]
tap> {:constraint nil
      :schema nil
      :SQLState "42P07"
      :where nil
      :table nil
      :internalPosition 0
      :datatype nil
      :file "heap.c"
      :hint nil
      :internalQuery nil
      :column nil
      :routine "heap_create_with_catalog"
      :line 1200
      :severity "ERROR"
      :position 0
      :message "relation \"repo\" already exists"
      :detail nil}