diff --git a/src/box/tuple.cc b/src/box/tuple.cc
index bef792946884442c1bd8ac363be3ece24f90ca36..2d3d877654588a389b58b175430549019fa16558 100644
--- a/src/box/tuple.cc
+++ b/src/box/tuple.cc
@@ -79,7 +79,8 @@ field_type_create(enum field_type *types, uint32_t field_count,
 			if (*ptype != UNKNOWN && *ptype != part->type) {
 				tnt_raise(ClientError,
 					  ER_FIELD_TYPE_MISMATCH,
-					  key_def->name, part - key_def->parts,
+					  key_def->name,
+					  part - key_def->parts + INDEX_OFFSET,
 					  field_type_strs[part->type],
 					  field_type_strs[*ptype]);
 			}
@@ -219,7 +220,8 @@ tuple_format_new(struct rlist *key_list)
  * format data.
  */
 void
-tuple_init_field_map(struct tuple_format *format, struct tuple *tuple, uint32_t *field_map)
+tuple_init_field_map(struct tuple_format *format, struct tuple *tuple,
+		     uint32_t *field_map)
 {
 	if (format->field_count == 0)
 		return; /* Nothing to initialize */
@@ -243,7 +245,8 @@ tuple_init_field_map(struct tuple_format *format, struct tuple *tuple, uint32_t
 		enum mp_type mp_type = mp_typeof(*pos);
 		mp_next(&pos);
 
-		key_mp_type_validate(*type, mp_type, ER_FIELD_TYPE, i);
+		key_mp_type_validate(*type, mp_type, ER_FIELD_TYPE,
+				     i + INDEX_OFFSET);
 
 		if (*offset < 0 && *offset != INT32_MIN)
 			field_map[*offset] = d - tuple->data;
@@ -356,7 +359,7 @@ tuple_next_cstr(struct tuple_iterator *it)
 	if (field == NULL)
 		tnt_raise(ClientError, ER_NO_SUCH_FIELD, fieldno);
 	if (mp_typeof(*field) != MP_STR)
-		tnt_raise(ClientError, ER_FIELD_TYPE, fieldno,
+		tnt_raise(ClientError, ER_FIELD_TYPE, fieldno + INDEX_OFFSET,
 			  field_type_strs[STRING]);
 	uint32_t len = 0;
 	const char *str = mp_decode_str(&field, &len);
@@ -376,7 +379,7 @@ tuple_field_cstr(struct tuple *tuple, uint32_t i)
 	if (field == NULL)
 		tnt_raise(ClientError, ER_NO_SUCH_FIELD, i);
 	if (mp_typeof(*field) != MP_STR)
-		tnt_raise(ClientError, ER_FIELD_TYPE, i,
+		tnt_raise(ClientError, ER_FIELD_TYPE, i + INDEX_OFFSET,
 			  field_type_strs[STRING]);
 	uint32_t len = 0;
 	const char *str = mp_decode_str(&field, &len);
@@ -628,7 +631,8 @@ double mp_decode_num(const char **data, uint32_t i)
 		val = mp_decode_double(data);
 		break;
 	default:
-		tnt_raise(ClientError, ER_FIELD_TYPE, i, field_type_strs[NUM]);
+		tnt_raise(ClientError, ER_FIELD_TYPE, i + INDEX_OFFSET,
+			  field_type_strs[NUM]);
 	}
 	return val;
 }
diff --git a/src/box/tuple.h b/src/box/tuple.h
index dd8d50d07919d45c47a17f39472b13ac2df3291a..4585a44d1ecfb030d99f3ab8f5433ce885b8e6b9 100644
--- a/src/box/tuple.h
+++ b/src/box/tuple.h
@@ -33,6 +33,12 @@
 
 enum { FORMAT_ID_MAX = UINT16_MAX - 1, FORMAT_ID_NIL = UINT16_MAX };
 enum { FORMAT_REF_MAX = INT32_MAX, TUPLE_REF_MAX = UINT16_MAX };
+/*
+ * We don't pass INDEX_OFFSET around dynamically all the time,
+ * at least hard code it so that in most cases it's a nice error
+ * message
+ */
+enum { INDEX_OFFSET = 1 };
 
 /** Common quota for tuples and indexes */
 extern struct quota memtx_quota;
@@ -323,11 +329,13 @@ tuple_field_u32(struct tuple *tuple, uint32_t i)
 	if (field == NULL)
 		tnt_raise(ClientError, ER_NO_SUCH_FIELD, i);
 	if (mp_typeof(*field) != MP_UINT)
-		tnt_raise(ClientError, ER_FIELD_TYPE, i, field_type_strs[NUM]);
+		tnt_raise(ClientError, ER_FIELD_TYPE, i + INDEX_OFFSET,
+			  field_type_strs[NUM]);
 
 	uint64_t val = mp_decode_uint(&field);
 	if (val > UINT32_MAX)
-		tnt_raise(ClientError, ER_FIELD_TYPE, i, field_type_strs[NUM]);
+		tnt_raise(ClientError, ER_FIELD_TYPE, i + INDEX_OFFSET,
+			  field_type_strs[NUM]);
 	return (uint32_t) val;
 }
 
@@ -427,12 +435,12 @@ tuple_next_u32(struct tuple_iterator *it)
 	if (field == NULL)
 		tnt_raise(ClientError, ER_NO_SUCH_FIELD, it->fieldno);
 	if (mp_typeof(*field) != MP_UINT)
-		tnt_raise(ClientError, ER_FIELD_TYPE, fieldno,
+		tnt_raise(ClientError, ER_FIELD_TYPE, fieldno + INDEX_OFFSET,
 			  field_type_strs[NUM]);
 
 	uint32_t val = mp_decode_uint(&field);
 	if (val > UINT32_MAX)
-		tnt_raise(ClientError, ER_FIELD_TYPE, fieldno,
+		tnt_raise(ClientError, ER_FIELD_TYPE, fieldno + INDEX_OFFSET,
 			  field_type_strs[NUM]);
 	return (uint32_t) val;
 }
diff --git a/test/big/hash.result b/test/big/hash.result
index b5a1ecc0e52c90114b27160f00f796c752a5443d..fb8ec35fe5b467771bf0be209179c7c89ca2c53e 100644
--- a/test/big/hash.result
+++ b/test/big/hash.result
@@ -40,7 +40,7 @@ tmp:bsize() > bsize
 -- Insert invalid fields
 hash:insert{'invalid key', 'value1 v1.0', 'value2 v1.0'}
 ---
-- error: 'Tuple field 0 type does not match one required by operation: expected NUM'
+- error: 'Tuple field 1 type does not match one required by operation: expected NUM'
 ...
 -------------------------------------------------------------------------------
 -- 32-bit hash replace fields tests
@@ -61,7 +61,7 @@ hash:replace{2, 'value1 v1.43', 'value2 1.92'}
 -- Replace invalid fields
 hash:replace{'invalid key', 'value1 v1.0', 'value2 v1.0'}
 ---
-- error: 'Tuple field 0 type does not match one required by operation: expected NUM'
+- error: 'Tuple field 1 type does not match one required by operation: expected NUM'
 ...
 -------------------------------------------------------------------------------
 -- 32-bit hash select fields test
@@ -178,7 +178,7 @@ hash:insert{103, 'value1 v1.0', 'value2 v1.0'}
 ...
 hash:insert{'invalid key', 'value1 v1.0', 'value2 v1.0'}
 ---
-- error: 'Tuple field 0 type does not match one required by operation: expected NUM'
+- error: 'Tuple field 1 type does not match one required by operation: expected NUM'
 ...
 -------------------------------------------------------------------------------
 -- 64-bit hash replace fields tests
@@ -211,7 +211,7 @@ hash:replace{2, 'value1 v1.43', 'value2 1.92'}
 ...
 hash:replace{'invalid key', 'value1 v1.0', 'value2 v1.0'}
 ---
-- error: 'Tuple field 0 type does not match one required by operation: expected NUM'
+- error: 'Tuple field 1 type does not match one required by operation: expected NUM'
 ...
 -------------------------------------------------------------------------------
 -- 64-bit hash select fields test
@@ -701,3 +701,19 @@ for _, tuple in hi:pairs(nil, {iterator = box.index.ALL}) do hash:delete{tuple[1
 hash:drop()
 ---
 ...
+-- 
+-- gh-616 "1-based indexing and 0-based error message
+--
+_ = box.schema.create_space('test')
+---
+...
+_ = box.space.test:create_index('i',{parts={1,'STR'}})
+---
+...
+box.space.test:insert{1}
+---
+- error: 'Tuple field 1 type does not match one required by operation: expected STR'
+...
+box.space.test:drop()
+---
+...
diff --git a/test/big/hash.test.lua b/test/big/hash.test.lua
index bf505b3c3fd5cd75f1485e16bf0b89e91b9e58a7..7fb2cb7c01cdbf092133c2f2922299419f30517f 100644
--- a/test/big/hash.test.lua
+++ b/test/big/hash.test.lua
@@ -299,3 +299,11 @@ hash:insert{0}
 hash:insert{16}
 for _, tuple in hi:pairs(nil, {iterator = box.index.ALL}) do hash:delete{tuple[1]} end
 hash:drop()
+
+-- 
+-- gh-616 "1-based indexing and 0-based error message
+--
+_ = box.schema.create_space('test')
+_ = box.space.test:create_index('i',{parts={1,'STR'}})
+box.space.test:insert{1}
+box.space.test:drop()
diff --git a/test/big/tree_pk.result b/test/big/tree_pk.result
index a8a3f3cf35623cbfd5286a127fb3db10c48ee96f..9a4b0da3cc0e524ae9d3f6bf7462d710a36cd020 100644
--- a/test/big/tree_pk.result
+++ b/test/big/tree_pk.result
@@ -64,15 +64,15 @@ s0:delete{3}
 -- https://bugs.launchpad.net/tarantool/+bug/1072624
 s0:insert{'xxxxxxx'}
 ---
-- error: 'Tuple field 0 type does not match one required by operation: expected NUM'
+- error: 'Tuple field 1 type does not match one required by operation: expected NUM'
 ...
 s0:insert{''}
 ---
-- error: 'Tuple field 0 type does not match one required by operation: expected NUM'
+- error: 'Tuple field 1 type does not match one required by operation: expected NUM'
 ...
 s0:insert{'12'}
 ---
-- error: 'Tuple field 0 type does not match one required by operation: expected NUM'
+- error: 'Tuple field 1 type does not match one required by operation: expected NUM'
 ...
 s1 = box.schema.space.create('tweedledee')
 ---
diff --git a/test/big/tree_variants.result b/test/big/tree_variants.result
index e72ecc90c2df10bfd01d1b5d8d94192a89f61838..5d48efe4e04dfa89a2221c1c477c08ac2bcd0177 100644
--- a/test/big/tree_variants.result
+++ b/test/big/tree_variants.result
@@ -179,19 +179,19 @@ sort(space:select{})
 -- https://bugs.launchpad.net/tarantool/+bug/1072624
 space:insert{'', 1, 2, '', '', '', '', '', 0}
 ---
-- error: 'Tuple field 0 type does not match one required by operation: expected NUM'
+- error: 'Tuple field 1 type does not match one required by operation: expected NUM'
 ...
 space:insert{'xxxxxxxx', 1, 2, '', '', '', '', '', 0}
 ---
-- error: 'Tuple field 0 type does not match one required by operation: expected NUM'
+- error: 'Tuple field 1 type does not match one required by operation: expected NUM'
 ...
 space:insert{1, '', 2, '', '', '', '', '', 0}
 ---
-- error: 'Tuple field 1 type does not match one required by operation: expected NUM'
+- error: 'Tuple field 2 type does not match one required by operation: expected NUM'
 ...
 space:insert{1, 'xxxxxxxxxxx', 2, '', '', '', '', '', 0}
 ---
-- error: 'Tuple field 1 type does not match one required by operation: expected NUM'
+- error: 'Tuple field 2 type does not match one required by operation: expected NUM'
 ...
 space:drop()
 ---
diff --git a/test/box/alter.result b/test/box/alter.result
index fa0ceaa292dd02d6c91c2a3c922b60ad0440e7df..0231006ccfada34478cb5a1d8ebc9a44dab8788c 100644
--- a/test/box/alter.result
+++ b/test/box/alter.result
@@ -20,7 +20,7 @@ _space:insert{_space.id, ADMIN, 'test', 5 }
 --
 _space:insert{'hello', 'world', 'test'}
 ---
-- error: 'Tuple field 0 type does not match one required by operation: expected NUM'
+- error: 'Tuple field 1 type does not match one required by operation: expected NUM'
 ...
 --
 -- Can't create a space which has wrong field count - field_count must be NUM
diff --git a/test/box/alter_limits.result b/test/box/alter_limits.result
index e38eaac1c153bb2d04112b58206e97ef89c7aa3f..406adb57dcbaf9af2f4c030a4ead7680a903af23 100644
--- a/test/box/alter_limits.result
+++ b/test/box/alter_limits.result
@@ -508,7 +508,7 @@ index = s:create_index('t1', { type = 'hash' })
 -- field type contradicts field type of another index
 index = s:create_index('t2', { type = 'hash', parts = { 1, 'str' }})
 ---
-- error: Ambiguous field type in index 't2', key part 0. Requested type is STR but
+- error: Ambiguous field type in index 't2', key part 1. Requested type is STR but
     the field has previously been defined as NUM
 ...
 -- ok
@@ -785,7 +785,7 @@ _ = box.space['_index']:update({s.id, s.index.year.id}, {{"=", 8, 'num'}})
 -- ambiguous field type
 index = s:create_index('str', { type = 'tree', unique =  false, parts = { 2, 'str'}})
 ---
-- error: Ambiguous field type in index 'str', key part 0. Requested type is STR but
+- error: Ambiguous field type in index 'str', key part 1. Requested type is STR but
     the field has previously been defined as NUM
 ...
 -- create index on a non-existing field
@@ -803,7 +803,7 @@ s:insert{'Der Baader Meinhof Komplex', '2009 '}
 -- create an index on a field with a wrong type
 index = s:create_index('year', { type = 'tree', unique = false, parts = { 2, 'num'}})
 ---
-- error: 'Tuple field 1 type does not match one required by operation: expected NUM'
+- error: 'Tuple field 2 type does not match one required by operation: expected NUM'
 ...
 -- a field is missing
 s:replace{'Der Baader Meinhof Komplex'}
diff --git a/test/box/rtree_misc.result b/test/box/rtree_misc.result
index 1cf45eed8eb93daaade27bb632fb6e00476a9fab..f356dac885bf27a91fdeb57adac9595d4749d7d8 100644
--- a/test/box/rtree_misc.result
+++ b/test/box/rtree_misc.result
@@ -44,11 +44,11 @@ i = s:create_index('secondary', { type = 'hash', parts = {2, 'num'}})
 -- adding a tuple with array instead of num will fail
 i = s:insert{{1, 2, 3}, 4}
 ---
-- error: 'Tuple field 0 type does not match one required by operation: expected NUM'
+- error: 'Tuple field 1 type does not match one required by operation: expected NUM'
 ...
 i = s:insert{1, {2, 3, 4}}
 ---
-- error: 'Tuple field 1 type does not match one required by operation: expected NUM'
+- error: 'Tuple field 2 type does not match one required by operation: expected NUM'
 ...
 -- rtree index must be one-part
 i = s:create_index('spatial', { type = 'rtree', unique = false, parts = {1, 'array', 2, 'array'}})
@@ -81,15 +81,15 @@ i = s:create_index('spatial', { type = 'rtree', unique = false, parts = {3, 'arr
 -- inserting wrong values (should fail)
 s:insert{1, 2, 3}
 ---
-- error: 'Tuple field 2 type does not match one required by operation: expected ARRAY'
+- error: 'Tuple field 3 type does not match one required by operation: expected ARRAY'
 ...
 s:insert{1, 2, "3"}
 ---
-- error: 'Tuple field 2 type does not match one required by operation: expected ARRAY'
+- error: 'Tuple field 3 type does not match one required by operation: expected ARRAY'
 ...
 s:insert{1, 2, nil, 3}
 ---
-- error: 'Tuple field 2 type does not match one required by operation: expected ARRAY'
+- error: 'Tuple field 3 type does not match one required by operation: expected ARRAY'
 ...
 s:insert{1, 2, {}}
 ---
@@ -98,23 +98,23 @@ s:insert{1, 2, {}}
 ...
 s:insert{1, 2, {"3", "4", "5", "6"}}
 ---
-- error: 'Tuple field 0 type does not match one required by operation: expected NUM'
+- error: 'Tuple field 1 type does not match one required by operation: expected NUM'
 ...
 s:insert{1, 2, {nil, 4, 5, 6}}
 ---
-- error: 'Tuple field 0 type does not match one required by operation: expected NUM'
+- error: 'Tuple field 1 type does not match one required by operation: expected NUM'
 ...
 s:insert{1, 2, {3, {4}, 5, 6}}
 ---
-- error: 'Tuple field 1 type does not match one required by operation: expected NUM'
+- error: 'Tuple field 2 type does not match one required by operation: expected NUM'
 ...
 s:insert{1, 2, {3, 4, {}, 6}}
 ---
-- error: 'Tuple field 2 type does not match one required by operation: expected NUM'
+- error: 'Tuple field 3 type does not match one required by operation: expected NUM'
 ...
 s:insert{1, 2, {3, 4, 5, "6"}}
 ---
-- error: 'Tuple field 3 type does not match one required by operation: expected NUM'
+- error: 'Tuple field 4 type does not match one required by operation: expected NUM'
 ...
 s:insert{1, 2, {3}}
 ---