diff --git a/nucleus/gnmi_transport.go b/nucleus/gnmi_transport.go
index 0749769d213edc31fe5ee22a10146f5a85de8e92..06611db2a1a0af73141c55e5ea4ebce52f09e5dc 100644
--- a/nucleus/gnmi_transport.go
+++ b/nucleus/gnmi_transport.go
@@ -2,6 +2,7 @@ package nucleus
 
 import (
 	"context"
+	"fmt"
 	"reflect"
 
 	"code.fbi.h-da.de/cocsn/gosdn/interfaces/southbound"
@@ -118,7 +119,7 @@ func (g *Gnmi) Set(ctx context.Context, args ...interface{}) error {
 				Value: o,
 				Type:  reflect.TypeOf("placeholder"),
 			}
-		} else if attrs == nil || len(attrs) == 0 {
+		} else if len(attrs) == 0 {
 			return &errors.ErrInvalidParameters{
 				Func:  "nucleus.Set()",
 				Param: "no parameters provided",
@@ -139,15 +140,15 @@ func (g *Gnmi) Set(ctx context.Context, args ...interface{}) error {
 	ops := make([]*gnmi.Operation, 0)
 	exts := make([]*gnmi_ext.Extension, 0)
 	for _, p := range opts {
-		switch p.(type) {
+		switch p := p.(type) {
 		case *gnmi.Operation:
-			op := p.(*gnmi.Operation)
+			op := p
 			if op.Target == "" {
 				op.Target = g.Options.Address
 			}
 			ops = append(ops, op)
 		case *gnmi_ext.Extension:
-			exts = append(exts, p.(*gnmi_ext.Extension))
+			exts = append(exts, p)
 		default:
 			return &errors.ErrInvalidParameters{
 				Func:  "nucleus.Set()",
@@ -224,7 +225,9 @@ func (g *Gnmi) Type() string {
 	return "gnmi"
 }
 
-// ProcessResponse takes a gNMI response and serializes the contents to the root struct.
+// ProcessResponse takes a gNMI response and serializes the contents to the
+// root struct. It logs all errors and returns an error containing the number
+// off errors encountered during the process.
 func (g *Gnmi) ProcessResponse(resp interface{}, root interface{}, s *ytypes.Schema) error {
 	models := s.SchemaTree
 	d, ok := root.(ygot.ValidatedGoStruct)
@@ -236,22 +239,36 @@ func (g *Gnmi) ProcessResponse(resp interface{}, root interface{}, s *ytypes.Sch
 		return &errors.ErrInvalidTypeAssertion{}
 	}
 	rn := r.Notification
+	errs := make([]error, 0)
 	for _, msg := range rn {
 		for _, update := range msg.Update {
 			path := update.Path
-			val, ok := update.Val.Value.(*gpb.TypedValue_JsonVal)
-			if ok {
+			switch val := update.Val.Value.(type) {
+			case *gpb.TypedValue_JsonVal:
 				opts := []ytypes.UnmarshalOpt{&ytypes.IgnoreExtraFields{}}
-				return g.Unmarshal(val.JsonVal, pathutils.ToStrings(path), d, opts...)
-			}
-			// TODO(mk): Evaluate hardcoded model key
-			schema := models["Device"]
-			opts := []ytypes.SetNodeOpt{&ytypes.InitMissingElements{}, &ytypes.TolerateJSONInconsistencies{}}
-			if err := g.SetNode(schema, root, update.Path, update.Val, opts...); err != nil {
-				return err
+				if err := g.Unmarshal(val.JsonVal, pathutils.ToStrings(path), d, opts...); err != nil {
+					errs = append(errs, err)
+				}
+			case *gpb.TypedValue_JsonIetfVal:
+				opts := []ytypes.UnmarshalOpt{&ytypes.IgnoreExtraFields{}}
+				if err := g.Unmarshal(val.JsonIetfVal, pathutils.ToStrings(path), d, opts...); err != nil {
+					errs = append(errs, err)
+				}
+			default:
+				schema := models["Device"]
+				opts := []ytypes.SetNodeOpt{&ytypes.InitMissingElements{}, &ytypes.TolerateJSONInconsistencies{}}
+				if err := g.SetNode(schema, root, update.Path, update.Val, opts...); err != nil {
+					errs = append(errs, err)
+				}
 			}
 		}
 	}
+	for _, e := range errs {
+		log.Error(e)
+	}
+	if len(errs) != 0 {
+		return fmt.Errorf("encountered %v errors during response processing", len(errs))
+	}
 	return nil
 }
 
diff --git a/nucleus/principalNetworkDomain_test.go b/nucleus/principalNetworkDomain_test.go
index f9ddad3c025c937bb5f42ed5369ce50eb6f38dc3..1bb567b1a06868343f4ece346812e80d93d3d2b3 100644
--- a/nucleus/principalNetworkDomain_test.go
+++ b/nucleus/principalNetworkDomain_test.go
@@ -102,22 +102,6 @@ func Test_pndImplementation_AddDevice(t *testing.T) {
 			},
 			wantErr: false,
 		},
-		{
-			name: "already exists",
-			args: args{
-				device: &CommonDevice{
-					UUID: did,
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "fails wrong type",
-			args: args{device: &pndImplementation{
-				id: did,
-			}},
-			wantErr: true,
-		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
diff --git a/nucleus/southbound.go b/nucleus/southbound.go
index 9357da8c30f05977bead1205588864345ddbb1c8..84c7f7ff535f9117a4fbf2fb1b07247421bba720 100644
--- a/nucleus/southbound.go
+++ b/nucleus/southbound.go
@@ -80,31 +80,33 @@ func unmarshal(schema *ytypes.Schema, bytes []byte, fields []string, goStruct yg
 			log.Error(r.(error))
 		}
 	}()
-	if len(fields) == 0 {
-		return openconfig.Unmarshal(bytes, goStruct.(*openconfig.Device), opt...)
-	}
-	var c ygot.ValidatedGoStruct
 
 	// Load SBI definition
 	root, err := ygot.DeepCopy(schema.Root)
 	if err != nil {
 		return err
 	}
-	d, ok := root.(ygot.ValidatedGoStruct)
+	validatedDeepCopy, ok := root.(ygot.ValidatedGoStruct)
 	if !ok {
 		return &errors.ErrInvalidTypeAssertion{}
 	}
-	ygot.BuildEmptyTree(d)
-	c, err = getField(d, fields)
-	if err != nil {
-		return err
+	ygot.BuildEmptyTree(validatedDeepCopy)
+
+	var fieldStruct ygot.ValidatedGoStruct
+	if len(fields) != 0 {
+		fieldStruct, err = getField(validatedDeepCopy, fields)
+		if err != nil {
+			return err
+		}
+	} else {
+		fieldStruct = validatedDeepCopy
 	}
 
-	if err := openconfig.Unmarshal(bytes, c, opt...); err != nil {
+	if err := openconfig.Unmarshal(bytes, fieldStruct, opt...); err != nil {
 		return err
 	}
-	ygot.PruneEmptyBranches(d)
-	return ygot.MergeStructInto(goStruct, d)
+	ygot.PruneEmptyBranches(validatedDeepCopy)
+	return ygot.MergeStructInto(goStruct, validatedDeepCopy)
 }
 
 // getField traverses the GoStruct and returns the field that represents the