diff --git a/src/common/namedb/namedb_lmdb.c b/src/common/namedb/namedb_lmdb.c
index 92bdfe6a078cb7fa17a6696eb1d26fb0713ad327..de6c4bb33a495f64be3fac7e303e05600e2c8e12 100644
--- a/src/common/namedb/namedb_lmdb.c
+++ b/src/common/namedb/namedb_lmdb.c
@@ -44,24 +44,43 @@ static int create_env_dir(const char *path)
 	return KNOT_EOK;
 }
 
+/*!
+ * \brief Convert error code returned by LMDB to Knot DNS error code.
+ *
+ * LMDB defines own error codes but uses additional ones from libc. All LMDB
+ * specific error codes are translated to KNOT_DATABASE_ERROR.
+ */
+static int lmdb_error_to_knot(int error)
+{
+	if (error == MDB_SUCCESS) {
+		return KNOT_EOK;
+	}
+
+	if (MDB_KEYEXIST <= error && error <= MDB_LAST_ERRCODE) {
+		return KNOT_DATABASE_ERROR;
+	}
+
+	return knot_errno_to_error(error);
+}
+
 static int dbase_open(struct lmdb_env *env, const char *path)
 {
 	int ret = mdb_env_create(&env->env);
 	if (ret != 0) {
-		return ret;
+		return lmdb_error_to_knot(ret);
 	}
 
 	long page_size = sysconf(_SC_PAGESIZE);
 	if (page_size <= 0) {
 		mdb_env_close(env->env);
-		return KNOT_ENOTSUP;
+		return KNOT_EINVAL;
 	}
 
 	size_t map_size = (LMDB_MAPSIZE / page_size) * page_size;
 	ret = mdb_env_set_mapsize(env->env, map_size);
 	if (ret != 0) {
 		mdb_env_close(env->env);
-		return ret;
+		return lmdb_error_to_knot(ret);
 	}
 
 	ret = create_env_dir(path);
@@ -73,27 +92,27 @@ static int dbase_open(struct lmdb_env *env, const char *path)
 	ret = mdb_env_open(env->env, path, 0, LMDB_FILE_MODE);
 	if (ret != 0) {
 		mdb_env_close(env->env);
-		return ret;
+		return lmdb_error_to_knot(ret);
 	}
 
 	MDB_txn *txn = NULL;
 	ret = mdb_txn_begin(env->env, NULL, 0, &txn);
 	if (ret != 0) {
 		mdb_env_close(env->env);
-		return ret;
+		return lmdb_error_to_knot(ret);
 	}
 
 	ret = mdb_open(txn, NULL, 0, &env->dbi);
 	if (ret != 0) {
 		mdb_txn_abort(txn);
 		mdb_env_close(env->env);
-		return ret;
+		return lmdb_error_to_knot(ret);
 	}
 
 	ret = mdb_txn_commit(txn);
 	if (ret != 0) {
 		mdb_env_close(env->env);
-		return ret;
+		return lmdb_error_to_knot(ret);
 	}
 
 	return 0;
@@ -116,7 +135,7 @@ static int init(const char *config, knot_namedb_t **db_ptr, mm_ctx_t *mm)
 	int ret = dbase_open(env, config);
 	if (ret != 0) {
 		mm_free(mm, env);
-		return KNOT_ERROR;
+		return ret;
 	}
 
 	env->pool = mm;
@@ -148,7 +167,7 @@ static int txn_begin(knot_namedb_t *db, knot_txn_t *txn, unsigned flags)
 	struct lmdb_env *env = db;
 	int ret = mdb_txn_begin(env->env, NULL, txn_flags, (MDB_txn **)&txn->txn);
 	if (ret != 0) {
-		return KNOT_ERROR;
+		return lmdb_error_to_knot(ret);
 	}
 
 	return KNOT_EOK;
@@ -158,7 +177,7 @@ static int txn_commit(knot_txn_t *txn)
 {
 	int ret = mdb_txn_commit((MDB_txn *)txn->txn);
 	if (ret != 0) {
-		return KNOT_ERROR;
+		return lmdb_error_to_knot(ret);
 	}
 
 	return KNOT_EOK;
@@ -176,7 +195,7 @@ static int count(knot_txn_t *txn)
 	MDB_stat stat;
 	int ret = mdb_stat(txn->txn, env->dbi, &stat);
 	if (ret != 0) {
-		return KNOT_ERROR;
+		return lmdb_error_to_knot(ret);
 	}
 
 	return stat.ms_entries;
@@ -188,7 +207,6 @@ static int find(knot_txn_t *txn, knot_val_t *key, knot_val_t *val, unsigned flag
 	MDB_val db_key = { key->len, key->data };
 	MDB_val data = { 0, NULL };
 
-
 	int ret = mdb_get(txn->txn, env->dbi, &db_key, &data);
 	if (ret != 0) {
 		if (ret == MDB_NOTFOUND) {
@@ -210,7 +228,7 @@ static int insert(knot_txn_t *txn, knot_val_t *key, knot_val_t *val, unsigned fl
 	MDB_cursor *cursor = NULL;
 	int ret = mdb_cursor_open(txn->txn, env->dbi, &cursor);
 	if (ret != 0) {
-		return KNOT_ERROR;
+		return lmdb_error_to_knot(ret);
 	}
 
 	MDB_val db_key = { key->len, key->data };
@@ -223,7 +241,7 @@ static int insert(knot_txn_t *txn, knot_val_t *key, knot_val_t *val, unsigned fl
 			// Insert new item
 			ret = mdb_put(txn->txn, env->dbi, &db_key, &data, 0);
 			if (ret != 0) {
-				return KNOT_ERROR;
+				return lmdb_error_to_knot(ret);
 			}
 
 			return KNOT_EOK;
@@ -235,7 +253,7 @@ static int insert(knot_txn_t *txn, knot_val_t *key, knot_val_t *val, unsigned fl
 	ret = mdb_cursor_put(cursor, &db_key, &data, MDB_CURRENT);
 	mdb_cursor_close(cursor);
 	if (ret != 0) {
-		return KNOT_ERROR;
+		return lmdb_error_to_knot(ret);
 	}
 
 	return KNOT_EOK;
@@ -249,7 +267,7 @@ static int del(knot_txn_t *txn, knot_val_t *key)
 
 	int ret = mdb_del(txn->txn, env->dbi, &db_key, &data);
 	if (ret != 0) {
-		return KNOT_ERROR;
+		return lmdb_error_to_knot(ret);
 	}
 
 	return KNOT_EOK;
@@ -294,7 +312,7 @@ static int iter_key(knot_iter_t *iter, knot_val_t *key)
 	MDB_val mdb_key, mdb_val;
 	int ret = mdb_cursor_get(cursor, &mdb_key, &mdb_val, MDB_GET_CURRENT);
 	if (ret != 0) {
-		return KNOT_ERROR;
+		return lmdb_error_to_knot(ret);
 	}
 
 	key->data = mdb_key.mv_data;
@@ -309,7 +327,7 @@ static int iter_val(knot_iter_t *iter, knot_val_t *val)
 	MDB_val mdb_key, mdb_val;
 	int ret = mdb_cursor_get(cursor, &mdb_key, &mdb_val, MDB_GET_CURRENT);
 	if (ret != 0) {
-		return KNOT_ERROR;
+		return lmdb_error_to_knot(ret);
 	}
 
 	val->data = mdb_val.mv_data;
diff --git a/src/libknot/errcode.c b/src/libknot/errcode.c
index a85f6a9d05fdc9fca4f01943abeb14851b24ba16..a54996675b924d8f84374defc735988ab990c965 100644
--- a/src/libknot/errcode.c
+++ b/src/libknot/errcode.c
@@ -120,6 +120,9 @@ const error_table_t error_messages[] = {
 	/* NSEC3 errors. */
 	{ KNOT_NSEC3_ECOMPUTE_HASH, "cannot compute NSEC3 hash" },
 
+	/* Dynamic backend errors. */
+	{ KNOT_DATABASE_ERROR, "unspecified database error" },
+
 	{ KNOT_ERROR, NULL } /* Terminator */
 };
 
diff --git a/src/libknot/errcode.h b/src/libknot/errcode.h
index 88bec58fc42a2ead7846a24488117f5f516d1e11..2b2b1fc5e5b59d831aa89203f6e7b1d7c6ccc30a 100644
--- a/src/libknot/errcode.h
+++ b/src/libknot/errcode.h
@@ -134,7 +134,10 @@ enum knot_error {
 	KNOT_DNSSEC_EMISSINGKEYTYPE,
 
 	/* NSEC3 errors. */
-	KNOT_NSEC3_ECOMPUTE_HASH
+	KNOT_NSEC3_ECOMPUTE_HASH,
+
+	/* Database backend. */
+	KNOT_DATABASE_ERROR
 };
 
 /*!
@@ -161,7 +164,7 @@ int knot_map_errno_internal(int fallback, int arg0, ...);
 /*!
  * \brief Map POSIX errno to Knot error code.
  *
- * KNOT_ERRNO is used as a fallback error, the list is terminated implicitly.
+ * KNOT_ERROR is used as a fallback error, the list is terminated implicitly.
  */
 #define knot_map_errno(errors...) knot_map_errno_internal(KNOT_ERROR, errors, 0)