Skip to content

[Bug]: Exception when transacting an tuple schema to the database #754

@JeremS

Description

@JeremS

What version of Datahike are you using?

0.6.1607

What version of Java are you using?

openjdk 24.0.2 2025-07-15

What operating system are you using?

Ubuntu

What database EDN configuration are you using?

{:store {:backend :mem :id "cfg1"} :attribute-refs? true}

Describe the bug

The ordering in which I declare the kvs for the map representing a :db/tupleAttrs schema matters. If the :db/ident comes first all is good, if it comes last a java.lang.ClassCastException is thrown with the message:

"class java.lang.Long cannot be cast to class clojure.lang.IFn (java.lang.Long is in module java.base of loader 'bootstrap'; clojure.lang.IFn is in unnamed module of loader 'app')"

In other words this will transact fine:

{:db/ident       :reg/semester+course+student 
  :db/valueType   :db.type/tuple
  :db/tupleAttrs  [:reg/course :reg/semester :reg/student]
  :db/cardinality :db.cardinality/one}])

While this will throw:

{ :db/valueType   :db.type/tuple
  :db/tupleAttrs  [:reg/course :reg/semester :reg/student]
  :db/cardinality :db.cardinality/one
  :db/ident       :reg/semester+course+student}])

What is the expected behaviour?

This problem may come from the ordering of the key value pairs in the underlying Clojure ArrayMap. This is the only thing I can think of that might influence the issue. The expected behavior would be for the transaction to go through regardless of that ordering.

How can the behaviour be reproduced?

Here is the code snippet I use to reproduce the problem in a repl:

(ns repro
  (:require
    [datahike.api :as d]))

;; -----------------------------------------------------------------------------
;; Example 1
;; -----------------------------------------------------------------------------
(def cfg1 {:store {:backend :mem :id "cfg1"} :attribute-refs?    true})
(d/create-database cfg1)
(def conn1 (d/connect cfg1))

;; here :db/ident is comes first
(def schema1
  [{:db/ident       :reg/semester+course+student 
    :db/valueType   :db.type/tuple
    :db/tupleAttrs  [:reg/course :reg/semester :reg/student]
    :db/cardinality :db.cardinality/one}])

(comment
  ;; The schema is accepted
  (d/transact conn1 schema1))

;; -----------------------------------------------------------------------------
;; Example 2
;; -----------------------------------------------------------------------------
(def cfg2 {:store {:backend :mem :id "cfg2"}
           :attribute-refs?    true})

(d/create-database cfg2)

(def conn2 (d/connect cfg2))

;; here :db/ident comes last
(def schema2
  [{:db/valueType   :db.type/tuple
    :db/tupleAttrs  [:reg/course :reg/semester :reg/student]
    :db/cardinality :db.cardinality/one
    :db/ident       :reg/semester+course+student}]) 

(comment
  ;; An exception is thrown
  (d/transact conn2 schema2))

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingtriage

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions