Inconsistency between query on peer and transact


I’m on “classic peer”
I have a datomic function :empty-query? that I use as transaction function

(def empty-query?
  (d/function '{:lang     :clojure
                :requires [[datomic.api :as d]]
                :params   [db query & args]
                :code     (when-not (->> (into [db] args)
                                         (hash-map :query query :args)
                            (throw (ex-info "FAIL" {})))}))

But some queries produce different result’s on peer and on transactor
For example

'[:find ?e
  :in $ ?ignore-set
  [?e :app/foo]
  (not [(contains? ?ignore-set ?e)])]

on peer(d/with and d/transact on “mem”) works “as expected”
on transact(d/transact on “dev”) always return “empty?”
Then I changed to

'[:find ?e
  :in $ ?ignore-set
  [?e :app/foo]
  [(contains? ?ignore-set ?e) ?q]
  [(ground false) ?q]]

That second one always returns the same results (“as expected”) on transactor and on peer.
Is it a bug?


I don’t understand what exactly fails here.
You’re not invoking your empty-query? function in either of the query examples you provide.


Thnks @marshall .
I’m using :empty-query as a Transaction function.
Example of use

(let [query '[:find ?e :where [?e :foo/bar]]]
  (d/transact conn [[:empty-query query][:db/add "foo" :foo/bar "bar"]])

But some queries has different behaviors when running in datomic:mem and datomic:dev.
When I say “on peer (d/with and d/transact on \“mem\”) works \“as expected\”” I’m saying that I have a tx-data that contains a [:empty-query ...] and when I transact this tx-data on datomic:mem or make a d/with on datomic:dev, it works as I expected (fail the tx, for example). But when I d/transact to datomic:dev, then the transaction is completed successfully.

A repl-driven explanation

(def mem-conn (create-and-install-sample-set-1 "datomic:mem://foo"))
(def dev-conn (create-and-install-sample-set-1 "datomic:dev://localhost:4334/foo"))
(def tx-data [[:empty-query ....] [:db/add ...]])
;; I expect that this tx-data fails becaulse `[:empty-query ...]` will find results 
(d/with (d/db mem-conn) tx-data) ;;; fail/throws; as expected
(d/with (d/db dev-conn) tx-data) ;;; fail/throws; as expected
@(d/transact mem-conn tx-data) ;;; fail/throws; as expected
@(d/transact dev-conn tx-data) ;; transact with success.; ???!!!????!!!

Then I change the query in :emtpty-query from (first query on first post) to (second query on first post). I think that are both equivalents. But just the first do the issue. The second works “as expected” on “4” cenarios.


For testing purposes on a dev transactor you should be able to include output statements (i.e. println) inside your transaction function and they will print to stdout in the terminal where you’re running your transactor.

I would suggest examining the arguments and the constructed query to determine why the query isn’t returning your expected result. In general, this type of issue arises when using a ‘remote’ transactor because the arguments to a transaction function arrive as a Java type in the remote case (dev), but not in the in-process case (mem and with).


Already did that
(prn [x (class x)]) all the things
The only relevant difference that I found was that (not [(contains? ?ignore-set ?e)]) turns into [not [[contains? ?ignore-set ?e]]].

The main problem is that in my tests on mem it works and when I go production, it fail. And it is for concurrency problems.
I will make a repo to reproduce ASAP



Easy gist to reproduce


Thanks for providing this.
We’re looking into the behavior.


@stu @marshall
Any news about that?
It will be fixed? There is a issue/tracking thing?