Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure RuntimeException - No reader function for tag db/id

What is happening when I get this error in Clojure?

java.lang.RuntimeException: No reader function for tag db/id
like image 737
Zefira Avatar asked Aug 23 '17 01:08

Zefira


1 Answers

Tagged Literals

This error message is related to a feature introduced in Clojure 1.7, tagged literals. Tagged literals are a simple means for extending what data types can be represented as literals in Clojure code or EDN data.

Clojure ships with readers for two tagged literals, #inst and #uuid allowing literal representations of java.util.Date and java.util.UUID. Support for more tags can be added by including data_readers.clj files on the classpath as described in the documentation.

Common causes

Some common causes of this error:

  • Trying to read Datomic transaction data containing #db/id literals
  • While attempting to use the EDN reader without passing :readers
  • In Boot tasks that try to use the EDN reader by passing *data-readers*.

Using the EDN reader

One common cause of this error is trying to use the EDN reader without passing the :readers option. From the doc string for clojure.edn/read:

:readers  - a map of tag symbols to data-reader functions to be
            considered before default-data-readers. When not
            supplied, only the default-data-readers will be used.

As its name implies, default-data-readers is only the map of data readers that ship with Clojure itself. That is, it does not include any readers defined in the data_readers.clj files of any libraries you are using (like, say, Datomic). The solution in this case is to pass the current set of loaded data readers, found in the var *data-readers*.

(clojure.edn/read {:readers *data-readers*} <your-read-source>)

Or, even better, explicitly specify the mapping of the data readers you want to use. For instance, if you want to be able to use only the datomic data readers:

(require 'datomic.db
         'datomic.function
         'datomic.codec)

(edn/read {:readers {'db/id  datomic.db/id-literal
                     'db/fn  datomic.function/construct
                     'base64 datomic.codec/base-64-literal}}
          <your-read-source-here>)

And of course, since these are just clojure maps we're dealing with, we could also include the default-data-readers by merging the maps:

(require 'datomic.db
         'datomic.function
         'datomic.codec)

(edn/read {:readers (merge
                     default-data-readers
                     {'db/id  datomic.db/id-literal
                      'db/fn  datomic.function/construct
                      'base64 datomic.codec/base-64-literal})}
          <your-read-source-here>)
like image 99
Zefira Avatar answered Oct 24 '22 05:10

Zefira