I'm getting a lot of errors related to multi_index after updating to the newest eosio.cdt. Here is part of my code related to hash.

struct st_hash {
   capi_checksum256 hash;
   uint64_t expiration;
   uint64_t primary_key() const { return uint64_hash(hash); }

   uint64_t by_expiration() const { return expiration; }

class testclass : public contract {
     testclass(name self) :
     _hash(_self, _self) {};

    tb_hash _hash;


typedef multi_index<
"hash"_n, st_hash,
           const_mem_fun<st_hash, uint64_t, &st_hash::by_expiration>>>

I am getting errors such as:

error: constexpr variable 'x' must be initialized by a constant expression
 ...x = eosio::name{std::string_view{eosio::detail::to_const_char_arr<Str...>::value, sizeof...(Str)}};

error: non-type template argument is not a constant

 error: excess elements in scalar initializer
      _hash(_self, _self),

 error: member reference base type 'tb_hash'
  (aka 'int') is not a structure or union
    auto itr = _hash.find(key);

error: no matching constructor for initialization of
  'tb_hash' (aka 'multi_index<operator""_n<char, 'h', 'a', 's', 'h'>(),
    : _hash(_self, _self),

 error: member reference base type 'tb_hash'
  (aka 'int') is not a structure or union
    _hash.emplace(_self, [&](st_hash& r) {

Any idea what I am doing wrong, or something needs to be changed to use new version of eosio CDT?

  • 'uint64_hash' what is this.? primary key should be of type 'uint' Commented Mar 5, 2019 at 7:50
  • It is just a function that converts the hash to uint64_t. I’m not getting any errors with that, I just left it out of the sample code in my post.
    – koukotsu
    Commented Mar 5, 2019 at 11:25
  • Your _hash table is not assign to a variable , another your class constructor is not according to eosio.cdt version. That's why it showing table name normalization error ` h a s h ` Commented Mar 6, 2019 at 5:16

2 Answers 2


There are huge differences between the old eosio-cpp, the first versions of the cdt and the actual one.

You don't have to initialize the table like you do while the constructor is called.

You also need to use the Abi-Generator-Attributes instead of multi-index-typedefs.

Take a look here: Abi-Generator-Attributes

And here: Basic Usage

  • If i don't initialise in the constructor I get: error: constructor for testclass explicitly initialize the member '_hash' which does not have a default constructor.
    – koukotsu
    Commented Mar 4, 2019 at 23:40
  • Also I thought the abi attributes only were relevant to generating the abi and not related to the build errors? Is this documentation out of date?: developers.eos.io/eosio-cpp/docs/using-multi-index-tables
    – koukotsu
    Commented Mar 4, 2019 at 23:42

One issue is that your secondary index is called "by_expiration" which is not a valid eosio::name.

It needs the same restrictions as any other name on EOSIO. Max 12 (actually 13) characters a-z0-5.

Another one is that your class constructor is still the old one. It has changed since eosio.cdt 1.3. You're also not initializing the superclass eosio::contract constructor. Note that the behavior of the multi-index also changed. It now accepts an eosio::name as the first argument but as the second argument it still requires an uint64_t. So you need to call .value on the second argument. Here's how I think it should look like:

CONTRACT testclass : public eosio::contract {
  testclass(eosio::name receiver, eosio::name code,
             eosio::datastream<const char *> ds)
      : contract(receiver, code, ds), _hash(receiver, receiver.value) {}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.