diff --git a/ChangeLog b/ChangeLog
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Version 0.0.2.3 2017-10-24 by luispedro
+	* Fix crashes on very large hashes
+
+Version 0.0.2.2 2017-10-23 by luispedro
+	* Better error message for ftruncate failures
+
 Version 0.0.2.1 2017-10-12 by luispedro
 	* Export reserve() in Python interface
 
diff --git a/diskhash.cabal b/diskhash.cabal
--- a/diskhash.cabal
+++ b/diskhash.cabal
@@ -1,5 +1,5 @@
 name:               diskhash
-version:            0.0.2.1
+version:            0.0.2.3
 synopsis:           Disk-based hash table
 description:        Disk-based hash table
 category:           Data
diff --git a/src/diskhash.c b/src/diskhash.c
--- a/src/diskhash.c
+++ b/src/diskhash.c
@@ -85,6 +85,7 @@
 
 static
 uint64_t get_table_at(const HashTable* ht, uint64_t ix) {
+    assert(ix < cheader_of(ht)->cursize_);
     if (is_64bit(ht)) {
         uint64_t* table = (uint64_t*)hashtable_of((HashTable*)ht);
         return table[ix];
@@ -112,7 +113,7 @@
                 "\tslots used = %ld\n"
                 "\n", cheader_of(ht)->magic, (int)cheader_of(ht)->cursize_, cheader_of(ht)->slots_used_);
 
-    int i;
+    uint64_t i;
     for (i = 0; i < cheader_of(ht)->cursize_; ++i) {
         fprintf(stderr, "\tTable [ %d ] = %d\n",(int)i, (int)get_table_at(ht, i));
     }
@@ -173,7 +174,12 @@
         needs_init = 1;
         rp->datasize_ = sizeof(HashTableHeader) + 7 * sizeof(uint32_t) + 3 * node_size_opts(opts);
         if (ftruncate(fd, rp->datasize_) < 0) {
-            if (err) { *err = strdup("Could not allocate disk space."); }
+            if (err) {
+                *err = malloc(256);
+                if (*err) {
+                    snprintf(*err, 256, "Could not allocate disk space. Error: %s.", strerror(errno));
+                }
+            }
             close(rp->fd_);
             free((char*)rp->fname_);
             free(rp);
@@ -263,11 +269,11 @@
     if (header_of(ht)->cursize_ / 2 > cap) {
         return header_of(ht)->cursize_ / 2;
     }
-    const int starting_slots = cheader_of(ht)->slots_used_;
-    const int min_slots = cap * 2 + 1;
-    int i = 0;
+    const uint64_t starting_slots = cheader_of(ht)->slots_used_;
+    const uint64_t min_slots = cap * 2 + 1;
+    uint64_t i = 0;
     while (primes[i] && primes[i] < min_slots) ++i;
-    const int n = primes[i];
+    const uint64_t n = primes[i];
     cap = n / 2;
     const size_t sizeof_table_elem = is_64bit(ht) ? sizeof(uint64_t) : sizeof(uint32_t);
     const size_t total_size = sizeof(HashTableHeader) + n * sizeof_table_elem + cap * node_size(ht);
@@ -285,7 +291,12 @@
         free((char*)temp_ht->fname_);
     }
     if (ftruncate(temp_ht->fd_, total_size) < 0) {
-        if (err) { *err = strdup("Could not allocate disk space."); }
+        if (err) {
+            *err = malloc(256);
+            if (*err) {
+                snprintf(*err, 256, "Could not allocate disk space. Error: %s.", strerror(errno));
+            }
+        }
         free((char*)temp_ht->fname_);
         free(temp_ht);
         return 0;
@@ -355,8 +366,8 @@
 }
 
 void* dht_lookup(const HashTable* ht, const char* key) {
-    int h = hash_key(key) % cheader_of(ht)->cursize_;
-    int i;
+    uint64_t h = hash_key(key) % cheader_of(ht)->cursize_;
+    uint64_t i;
     for (i = 0; i < cheader_of(ht)->cursize_; ++i) {
         HashTableEntry et = entry_at(ht, h);
         if (!et.ht_key) return NULL;
@@ -381,7 +392,7 @@
     if (cheader_of(ht)->cursize_ / 2 <= cheader_of(ht)->slots_used_) {
         if (!dht_reserve(ht, cheader_of(ht)->slots_used_ + 1, err)) return -ENOMEM;
     }
-    int h = hash_key(key) % cheader_of(ht)->cursize_;
+    uint64_t h = hash_key(key) % cheader_of(ht)->cursize_;
     while (1) {
         HashTableEntry et = entry_at(ht, h);
         if (entry_empty(et)) break;
