Repository: mitchellh/mapstructure
Pull request #201 (2020-06-23 18:02:29)

Print value in error messages
In error messages like `'Key' expected type 'float64', got type 'string'` I think it's also useful to append the actual value.


Patch:
diff --git a/mapstructure.go b/mapstructure.go
index b384d9d..f3f8555 100644
--- a/mapstructure.go
+++ b/mapstructure.go
@@ -562,8 +562,8 @@ func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value)
 
 	if !converted {
 		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s'",
-			name, val.Type(), dataVal.Type())
+			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
+			name, val.Type(), dataVal.Type(), data)
 	}
 
 	return nil
@@ -604,8 +604,8 @@ func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) er
 		val.SetInt(i)
 	default:
 		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s'",
-			name, val.Type(), dataVal.Type())
+			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
+			name, val.Type(), dataVal.Type(), data)
 	}
 
 	return nil
@@ -660,8 +660,8 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e
 		val.SetUint(uint64(i))
 	default:
 		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s'",
-			name, val.Type(), dataVal.Type())
+			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
+			name, val.Type(), dataVal.Type(), data)
 	}
 
 	return nil
@@ -691,8 +691,8 @@ func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) e
 		}
 	default:
 		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s'",
-			name, val.Type(), dataVal.Type())
+			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
+			name, val.Type(), dataVal.Type(), data)
 	}
 
 	return nil
@@ -733,8 +733,8 @@ func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value)
 		val.SetFloat(i)
 	default:
 		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s'",
-			name, val.Type(), dataVal.Type())
+			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
+			name, val.Type(), dataVal.Type(), data)
 	}
 
 	return nil
@@ -984,8 +984,8 @@ func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) e
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 	if val.Type() != dataVal.Type() {
 		return fmt.Errorf(
-			"'%s' expected type '%s', got unconvertible type '%s'",
-			name, val.Type(), dataVal.Type())
+			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
+			name, val.Type(), dataVal.Type(), data)
 	}
 	val.Set(dataVal)
 	return nil


Test patch:
diff --git a/mapstructure_examples_test.go b/mapstructure_examples_test.go
index a52ff77..2413b69 100644
--- a/mapstructure_examples_test.go
+++ b/mapstructure_examples_test.go
@@ -62,11 +62,11 @@ func ExampleDecode_errors() {
 	// Output:
 	// 5 error(s) decoding:
 	//
-	// * 'Age' expected type 'int', got unconvertible type 'string'
-	// * 'Emails[0]' expected type 'string', got unconvertible type 'int'
-	// * 'Emails[1]' expected type 'string', got unconvertible type 'int'
-	// * 'Emails[2]' expected type 'string', got unconvertible type 'int'
-	// * 'Name' expected type 'string', got unconvertible type 'int'
+	// * 'Age' expected type 'int', got unconvertible type 'string', value: 'bad value'
+	// * 'Emails[0]' expected type 'string', got unconvertible type 'int', value: '1'
+	// * 'Emails[1]' expected type 'string', got unconvertible type 'int', value: '2'
+	// * 'Emails[2]' expected type 'string', got unconvertible type 'int', value: '3'
+	// * 'Name' expected type 'string', got unconvertible type 'int', value: '123'
 }
 
 func ExampleDecode_metadata() {
diff --git a/mapstructure_test.go b/mapstructure_test.go
index 63614e8..48eb256 100644
--- a/mapstructure_test.go
+++ b/mapstructure_test.go
@@ -2013,7 +2013,8 @@ func TestInvalidType(t *testing.T) {
 		t.Fatalf("error should be kind of Error, instead: %#v", err)
 	}
 
-	if derr.Errors[0] != "'Vstring' expected type 'string', got unconvertible type 'int'" {
+	if derr.Errors[0] !=
+		"'Vstring' expected type 'string', got unconvertible type 'int', value: '42'" {
 		t.Errorf("got unexpected error: %s", err)
 	}