Exception transacting schema

Attempting to transact schema to a Datomic Cloud DB, getting the following exception:

                         clojure.core/eval  core.clj: 3206
                                        ...                
      compute.db.core_test$eval21762.invoke          :    1
compute.db.core_test$eval21762.invokeStatic          :    1
           datomic.client.api/eval3011/fn/G   api.clj:  127
       datomic.client.api.sync/eval20111/fn  sync.clj:   89
               datomic.client.api.sync/ares  sync.clj:   30
                       clojure.core/ex-info  core.clj: 4739
clojure.lang.ExceptionInfo: Value of :db.install/attribute must be in :db.part/db partition, found :workload/maximum-instances
                               a: :db.install/attribute
    cognitect.anomalies/category: :cognitect.anomalies/incorrect
     cognitect.anomalies/message: "Value of :db.install/attribute must be in :db.part/db partition, found :workload/maximum-instances"
                        db/error: :db.error/not-in-system-partition
                             dbs: [{:database-id "382aa9d2-245d-4a00-b432-12e1310f7f90",
                                    :t 5,
                                    :next-t 6,
                                    :history false}]
                               v: :workload/maximum-instances

The attribute associated with the exception varies with different calls. The example in Getting Started seems to work, though if I fiddle around with it failures sometimes occur, but with no reliable repro. Schema below. This works fine with on-prem.

[#:db{:valueType :db.type/uuid,
      :cardinality :db.cardinality/one,
      :ident :compute.data-model.command/id,
      :unique :db.unique/identity}
 #:db{:valueType :db.type/keyword,
      :cardinality :db.cardinality/one,
      :ident :entity/type}
 #:db{:valueType :db.type/string,
      :cardinality :db.cardinality/one,
      :ident :compute.data-model.entity/name}
 #:db{:valueType :db.type/uuid,
      :cardinality :db.cardinality/one,
      :ident :entity/id,
      :unique :db.unique/identity}
 #:db{:valueType :db.type/string,
      :cardinality :db.cardinality/one,
      :ident :user/email,
      :unique :db.unique/identity}
 #:db{:valueType :db.type/string,
      :cardinality :db.cardinality/one,
      :ident :user/job-title}
 #:db{:valueType :db.type/string,
      :cardinality :db.cardinality/one,
      :ident :user/name}
 #:db{:valueType :db.type/string,
      :cardinality :db.cardinality/one,
      :ident :user/password}
 #:db{:valueType :db.type/string,
      :cardinality :db.cardinality/one,
      :ident :customer/name}
 #:db{:cardinality :db.cardinality/many,
      :valueType :db.type/ref,
      :ident :customer/users,
      :isComponent true}
 #:db{:cardinality :db.cardinality/many,
      :valueType :db.type/ref,
      :ident :customer/workloads,
      :isComponent true}
 #:db{:cardinality :db.cardinality/many,
      :valueType :db.type/ref,
      :ident :customer/deployments,
      :isComponent true}
 #:db{:valueType :db.type/string,
      :cardinality :db.cardinality/one,
      :ident :workload/name}
 #:db{:valueType :db.type/string,
      :cardinality :db.cardinality/one,
      :ident :workload/description}
 #:db{:valueType :db.type/keyword,
      :cardinality :db.cardinality/one,
      :ident :workload/schedule-entry-method}
 #:db{:valueType :db.type/double,
      :cardinality :db.cardinality/one,
      :ident :workload/minimum-completion-time}
 #:db{:valueType :db.type/double,
      :cardinality :db.cardinality/one,
      :ident :workload/completion-time-50th-%ile}
 #:db{:valueType :db.type/double,
      :cardinality :db.cardinality/one,
      :ident :workload/completion-time-90th-%ile}
 #:db{:valueType :db.type/double,
      :cardinality :db.cardinality/one,
      :ident :workload/instance-spin-up-time}
 #:db{:valueType :db.type/keyword,
      :cardinality :db.cardinality/one,
      :ident :workload/workload-type}
 #:db{:valueType :db.type/double,
      :cardinality :db.cardinality/one,
      :ident :workload/average-workloads-per-day}
 #:db{:valueType :db.type/double,
      :cardinality :db.cardinality/one,
      :ident :workload/average-completion-time}
 #:db{:valueType :db.type/string,
      :cardinality :db.cardinality/one,
      :ident :workload/start-time}
 #:db{:cardinality :db.cardinality/many,
      :valueType :db.type/ref,
      :ident :workload/impacts,
      :isComponent true}
 #:db{:valueType :db.type/boolean,
      :cardinality :db.cardinality/one,
      :ident :workload/workload-checkpointed?}
 #:db{:valueType :db.type/double,
      :cardinality :db.cardinality/one,
      :ident :workload/checkpoint-frequency}
 #:db{:valueType :db.type/boolean,
      :cardinality :db.cardinality/one,
      :ident :workload/can-move-azs?}
 #:db{:valueType :db.type/boolean,
      :cardinality :db.cardinality/one,
      :ident :workload/can-move-regions?}
 #:db{:valueType :db.type/boolean,
      :cardinality :db.cardinality/one,
      :ident :workload/completed?}
 #:db{:valueType :db.type/string,
      :cardinality :db.cardinality/one,
      :ident :workload/instance-type}
 #:db{:valueType :db.type/long,
      :cardinality :db.cardinality/one,
      :ident :workload/minimum-instances}
 #:db{:valueType :db.type/long,
      :cardinality :db.cardinality/one,
      :ident :workload/maximum-instances}
 #:db{:cardinality :db.cardinality/many,
      :valueType :db.type/ref,
      :ident :workload/simulations,
      :isComponent true}
 #:db{:valueType :db.type/boolean,
      :cardinality :db.cardinality/one,
      :ident :workload/autoscale-demo}
 #:db{:valueType :db.type/double,
      :cardinality :db.cardinality/one,
      :ident :workload/minimum-completion-time-ms}
 #:db{:valueType :db.type/keyword,
      :cardinality :db.cardinality/one,
      :ident :workload/minimum-completion-time-unit}
 #:db{:valueType :db.type/double,
      :cardinality :db.cardinality/one,
      :ident :workload/completion-time-50th-%ile-ms}
 #:db{:valueType :db.type/keyword,
      :cardinality :db.cardinality/one,
      :ident :workload/completion-time-50th-%ile-unit}
 #:db{:valueType :db.type/double,
      :cardinality :db.cardinality/one,
      :ident :workload/completion-time-90th-%ile-ms}
 #:db{:valueType :db.type/keyword,
      :cardinality :db.cardinality/one,
      :ident :workload/completion-time-90th-%ile-unit}
 #:db{:valueType :db.type/double,
      :cardinality :db.cardinality/one,
      :ident :workload/instance-spin-up-time-ms}
 #:db{:valueType :db.type/keyword,
      :cardinality :db.cardinality/one,
      :ident :workload/instance-spin-up-time-unit}
 #:db{:valueType :db.type/double,
      :cardinality :db.cardinality/one,
      :ident :workload/average-completion-time-ms}
 #:db{:valueType :db.type/keyword,
      :cardinality :db.cardinality/one,
      :ident :workload/average-completion-time-unit}
 #:db{:valueType :db.type/string,
      :cardinality :db.cardinality/one,
      :ident :impact/title}
 #:db{:valueType :db.type/string,
      :cardinality :db.cardinality/one,
      :ident :impact/description}
 #:db{:valueType :db.type/keyword,
      :cardinality :db.cardinality/one,
      :ident :impact/completion-measurement-method}
 #:db{:valueType :db.type/keyword,
      :cardinality :db.cardinality/one,
      :ident :impact/type}
 #:db{:valueType :db.type/double,
      :cardinality :db.cardinality/one,
      :ident :impact/cutoff-time}
 #:db{:cardinality :db.cardinality/many,
      :valueType :db.type/ref,
      :ident :impact/tiers,
      :isComponent true}
 #:db{:valueType :db.type/double,
      :cardinality :db.cardinality/one,
      :ident :impact/cutoff-time-ms}
 #:db{:valueType :db.type/keyword,
      :cardinality :db.cardinality/one,
      :ident :impact/cutoff-time-unit}
 #:db{:valueType :db.type/double,
      :cardinality :db.cardinality/one,
      :ident :tier/upper-bound.hours}
 #:db{:valueType :db.type/long,
      :cardinality :db.cardinality/one,
      :ident :tier/upper-bound.percentage}
 #:db{:valueType :db.type/double,
      :cardinality :db.cardinality/one,
      :ident :tier/cost}
 #:db{:valueType :db.type/double,
      :cardinality :db.cardinality/one,
      :ident :tier/upper-bound.ms}
 #:db{:valueType :db.type/keyword,
      :cardinality :db.cardinality/one,
      :ident :tier/upper-bound.ms-unit}
 #:db{:valueType :db.type/boolean,
      :cardinality :db.cardinality/one,
      :ident :historical-data-upload/valid?}
 #:db{:valueType :db.type/keyword,
      :cardinality :db.cardinality/one,
      :ident :historical-data-upload/content-type}
 #:db{:valueType :db.type/keyword,
      :cardinality :db.cardinality/one,
      :ident :historical-data-upload/field}
 #:db{:valueType :db.type/instant,
      :cardinality :db.cardinality/one,
      :ident :alert/inst}
 #:db{:valueType :db.type/keyword,
      :cardinality :db.cardinality/one,
      :ident :alert/type}
 #:db{:valueType :db.type/boolean,
      :cardinality :db.cardinality/one,
      :ident :alert/dismissed?}
 #:db{:valueType :db.type/string,
      :cardinality :db.cardinality/one,
      :ident :deployment/name}
 #:db{:valueType :db.type/ref,
      :cardinality :db.cardinality/one,
      :ident :deployment/workload}
 #:db{:cardinality :db.cardinality/many,
      :valueType :db.type/ref,
      :ident :deployment/alerts,
      :isComponent true}
 #:db{:valueType :db.type/ref,
      :cardinality :db.cardinality/one,
      :ident :deployment/summary,
      :isComponent true}
 #:db{:valueType :db.type/string,
      :cardinality :db.cardinality/one,
      :ident :simulation/name}
 #:db{:valueType :db.type/long,
      :cardinality :db.cardinality/one,
      :ident :simulation/time-period-ms}
 #:db{:valueType :db.type/long,
      :cardinality :db.cardinality/one,
      :ident :simulation/workload-t}
 #:db{:valueType :db.type/ref,
      :cardinality :db.cardinality/one,
      :ident :simulation/summary,
      :isComponent true}
 #:db{:valueType :db.type/instant,
      :cardinality :db.cardinality/one,
      :ident :simulation/creation-date}
 #:db{:valueType :db.type/long,
      :cardinality :db.cardinality/one,
      :ident :simulation/request-period-ms}
 #:db{:valueType :db.type/instant,
      :cardinality :db.cardinality/one,
      :ident :simulation/start-time}
 #:db{:valueType :db.type/string,
      :cardinality :db.cardinality/one,
      :ident :upload/name}
 #:db{:valueType :db.type/long,
      :cardinality :db.cardinality/one,
      :ident :upload/byte-size}
 #:db{:valueType :db.type/string,
      :cardinality :db.cardinality/one,
      :ident :upload/uri}
 #:db{:valueType :db.type/ref,
      :cardinality :db.cardinality/one,
      :ident :audit/user}]

Update: seems to work as long as the :db/ident is the “first” entry in the attribute definition map, e.g.

(d/transact conn (mapv #(into (select-keys % [:db/ident]) %) schema))

I just ran into this as well. Here’s a minimal example:

(let [conn (d/connect client {:db-name "foo"})]
  (d/transact conn {:tx-data [#:db{:valueType :db.type/instant, :cardinality :db.cardinality/one, :ident :foo/bar}]}))
clojure.lang.ExceptionInfo: Value of :db.install/attribute must be in :db.part/db partition, found :foo/bar

As @sparkofreason said, if you move :db/ident to be the first key in the map, it works.

(let [conn (d/connect client {:db-name "foo"})]
  (d/transact conn {:tx-data [#:db{:ident :session/last-used-on :valueType :db.type/instant, :cardinality :db.cardinality/one}]}))
=>
{:db-before {:database-id "ae464fcb-0bc3-48f3-b3a4-3c8e9eff1d5a",
             :db-name "foo",
             :t 3,
             :next-t 4,
             :type :datomic.client/db},
 :db-after {:database-id "ae464fcb-0bc3-48f3-b3a4-3c8e9eff1d5a",
            :db-name "foo",
            :t 4,
            :next-t 5,
            :type :datomic.client/db},
 :tx-data [#datom[13194139533316 50 #inst"2018-10-18T18:08:00.642-00:00" 13194139533316 true]
           #datom[64 10 :foo/bar 13194139533316 true]
           #datom[64 40 25 13194139533316 true]
           #datom[64 41 35 13194139533316 true]
           #datom[0 13 64 13194139533316 true]],
 :tempids {}}

After asking in #datomic in on Clojurians Slack, @marshall said this is a bug in Datomic and he would pass it along to the team.