validation FEATURE optional diff creation
diff --git a/src/context.c b/src/context.c
index f4301c2..302638e 100644
--- a/src/context.c
+++ b/src/context.c
@@ -781,7 +781,7 @@
         root_bis = 0;
     }
 
-    if (lyd_validate(&root, NULL, LYD_VALIDATE_PRESENT)) {
+    if (lyd_validate(&root, NULL, LYD_VALIDATE_PRESENT, NULL)) {
         goto error;
     }
 
diff --git a/src/parser_data.h b/src/parser_data.h
index e12b65e..7bf68b2 100644
--- a/src/parser_data.h
+++ b/src/parser_data.h
@@ -100,8 +100,6 @@
  */
 #define LYD_VALIDATE_NO_STATE     0x0001    /**< Consider state data not allowed and raise an error if they are found. */
 #define LYD_VALIDATE_PRESENT      0x0002    /**< Validate only modules whose data actually exist. */
-//#define LYD_VALIDATE_DIFF         0x0004    /**< Flag only for validation, store all the data node changes performed by the validation
-//                                                 in a diff structure. */
 
 /** @} datavalidationoptions */
 
@@ -248,10 +246,11 @@
  * @param[in,out] tree Data tree to recursively validate. May be changed by validation.
  * @param[in] ctx libyang context. Can be NULL if @p tree is set.
  * @param[in] val_opts Validation options (@ref datavalidationoptions).
+ * @param[out] diff Optional diff with any changes made by the validation.
  * @return LY_SUCCESS on success.
  * @return LY_ERR error on error.
  */
-LY_ERR lyd_validate(struct lyd_node **tree, const struct ly_ctx *ctx, int val_opts);
+LY_ERR lyd_validate(struct lyd_node **tree, const struct ly_ctx *ctx, int val_opts, struct lyd_node **diff);
 
 /**
  * @brief Fully validate a data tree of a module.
@@ -259,10 +258,11 @@
  * @param[in,out] tree Data tree to recursively validate. May be changed by validation.
  * @param[in] module Module whose data (and schema restrictions) to validate.
  * @param[in] val_opts Validation options (@ref datavalidationoptions).
+ * @param[out] diff Optional diff with any changes made by the validation.
  * @return LY_SUCCESS on success.
  * @return LY_ERR error on error.
  */
-LY_ERR lyd_validate_module(struct lyd_node **tree, const struct lys_module *module, int val_opts);
+LY_ERR lyd_validate_module(struct lyd_node **tree, const struct lys_module *module, int val_opts, struct lyd_node **diff);
 
 /**
  * @brief Validate an RPC/action, notification, or RPC/action reply.
@@ -272,12 +272,13 @@
  * @param[in] tree Tree to be used for validating references from the operation subtree.
  * @param[in] op Operation to validate (@ref datavalidateop), the given @p op_tree must correspond to this value. Note that
  * it isn't possible to detect the operation simply from the @p op_tree since RPC/action and their reply share the same
- * RPC/action data node and in case one of the input and output do not define any data node children, it is not passible
+ * RPC/action data node and in case one of the input and output do not define any data node children, it is not possible
  * to get know what is here given for validation and if it is really valid.
+ * @param[out] diff Optional diff with any changes made by the validation.
  * @return LY_SUCCESS on success.
  * @return LY_ERR error on error.
  */
-LY_ERR lyd_validate_op(struct lyd_node *op_tree, const struct lyd_node *tree, LYD_VALIDATE_OP op);
+LY_ERR lyd_validate_op(struct lyd_node *op_tree, const struct lyd_node *tree, LYD_VALIDATE_OP op, struct lyd_node **diff);
 
 /** @} datatree */
 
diff --git a/src/parser_lyb.c b/src/parser_lyb.c
index 91d9b2c..0523bce 100644
--- a/src/parser_lyb.c
+++ b/src/parser_lyb.c
@@ -819,12 +819,12 @@
 
         if (!(lybctx->parse_options & LYD_PARSE_ONLY)) {
             /* new node validation, autodelete CANNOT occur, all nodes are new */
-            ret = lyd_validate_new(lyd_node_children_p(node), snode, NULL);
+            ret = lyd_validate_new(lyd_node_children_p(node), snode, NULL, NULL);
             LY_CHECK_GOTO(ret, cleanup);
 
             /* add any missing default children */
             ret = lyd_validate_defaults_r(node, lyd_node_children_p(node), NULL, NULL, &lybctx->unres_node_type,
-                                          &lybctx->when_check, lybctx->validate_options);
+                                          &lybctx->when_check, lybctx->validate_options, NULL);
             LY_CHECK_GOTO(ret, cleanup);
         }
 
diff --git a/src/parser_xml.c b/src/parser_xml.c
index 8c1e36d..3a3dee3 100644
--- a/src/parser_xml.c
+++ b/src/parser_xml.c
@@ -588,12 +588,12 @@
 
             if (!(lydctx->options & LYD_PARSE_ONLY)) {
                 /* new node validation, autodelete CANNOT occur, all nodes are new */
-                ret = lyd_validate_new(lyd_node_children_p(cur), snode, NULL);
+                ret = lyd_validate_new(lyd_node_children_p(cur), snode, NULL, NULL);
                 LY_CHECK_GOTO(ret, cleanup);
 
                 /* add any missing default children */
                 ret = lyd_validate_defaults_r(cur, lyd_node_children_p(cur), NULL, NULL, &lydctx->unres_node_type,
-                                              &lydctx->when_check, lydctx->options);
+                                              &lydctx->when_check, lydctx->options, NULL);
                 LY_CHECK_GOTO(ret, cleanup);
             }
 
@@ -714,15 +714,16 @@
             }
 
             /* validate new top-level nodes, autodelete CANNOT occur, all nodes are new */
-            LY_CHECK_GOTO(ret = lyd_validate_new(first2, NULL, mod), cleanup);
+            LY_CHECK_GOTO(ret = lyd_validate_new(first2, NULL, mod, NULL), cleanup);
 
             /* add all top-level defaults for this module */
-            ret = lyd_validate_defaults_r(NULL, first2, NULL, mod, &lydctx.unres_node_type, &lydctx.when_check, validate_options);
+            ret = lyd_validate_defaults_r(NULL, first2, NULL, mod, &lydctx.unres_node_type, &lydctx.when_check,
+                                          validate_options, NULL);
             LY_CHECK_GOTO(ret, cleanup);
 
             /* finish incompletely validated terminal values/attributes and when conditions */
             ret = lyd_validate_unres(tree, &lydctx.when_check, &lydctx.unres_node_type, &lydctx.unres_meta_type, LYD_XML,
-                                     lydxml_resolve_prefix, lydctx.xmlctx);
+                                     lydxml_resolve_prefix, lydctx.xmlctx, NULL);
             LY_CHECK_GOTO(ret, cleanup);
 
             /* perform final validation that assumes the data tree is final */
diff --git a/src/validation.c b/src/validation.c
index c550dc6..631fde6 100644
--- a/src/validation.c
+++ b/src/validation.c
@@ -21,6 +21,7 @@
 
 #include "common.h"
 #include "config.h"
+#include "diff.h"
 #include "hash_table.h"
 #include "log.h"
 #include "parser_data.h"
@@ -97,17 +98,44 @@
 }
 
 /**
+ * @brief Add new changes into validation diff. They are always merged.
+ *
+ * @param[in] node Node/subtree to add.
+ * @param[in] op Operation of the change.
+ * @param[in,out] diff Validation diff.
+ * @return LY_ERR value.
+ */
+static LY_ERR
+lyd_val_diff_add(const struct lyd_node *node, enum lyd_diff_op op, struct lyd_node **diff)
+{
+    LY_ERR ret = LY_SUCCESS;
+    struct lyd_node *new_diff = NULL;
+
+    assert((op == LYD_DIFF_OP_DELETE) || (op == LYD_DIFF_OP_CREATE));
+
+    /* create new diff tree */
+    LY_CHECK_RET(lyd_diff_add(node, op, NULL, NULL, NULL, NULL, NULL, &new_diff));
+
+    /* merge into existing diff */
+    ret = lyd_diff_merge(new_diff, diff);
+
+    lyd_free_tree(new_diff);
+    return ret;
+}
+
+/**
  * @brief Evaluate a single "when" condition.
  *
  * @param[in,out] tree Data tree, is updated if some nodes are autodeleted.
  * @param[in] node Node whose existence depends on this when.
  * @param[in] when When to evaluate.
+ * @param[in,out] diff Validation diff.
  * @return LY_ERR value (LY_EINCOMPLETE if a referenced node does not have its when evaluated)
  */
 static LY_ERR
-lyd_validate_when(struct lyd_node **tree, struct lyd_node *node, struct lysc_when *when)
+lyd_validate_when(struct lyd_node **tree, struct lyd_node *node, struct lysc_when *when, struct lyd_node **diff)
 {
-    LY_ERR ret = LY_SUCCESS;
+    LY_ERR ret;
     const struct lyd_node *ctx_node;
     struct lyxp_set xp_set;
 
@@ -135,11 +163,15 @@
             if (LYD_DEL_IS_ROOT(*tree, node)) {
                 *tree = (*tree)->next;
             }
+            if (diff) {
+                /* add into diff */
+                LY_CHECK_RET(lyd_val_diff_add(node, LYD_DIFF_OP_DELETE, diff));
+            }
             lyd_free_tree(node);
         } else {
             /* invalid data */
             LOGVAL(LYD_NODE_CTX(node), LY_VLOG_LYD, node, LY_VCODE_NOWHEN, when->cond->expr);
-            ret = LY_EVALID;
+            return LY_EVALID;
         }
     } else {
         /* remember that when evaluated to true */
@@ -151,7 +183,7 @@
 
 LY_ERR
 lyd_validate_unres(struct lyd_node **tree, struct ly_set *node_when, struct ly_set *node_types, struct ly_set *meta_types,
-                   LYD_FORMAT format, ly_clb_resolve_prefix get_prefix_clb, void *parser_data)
+                   LYD_FORMAT format, ly_clb_resolve_prefix get_prefix_clb, void *parser_data, struct lyd_node **diff)
 {
     LY_ERR ret = LY_SUCCESS;
     uint32_t i;
@@ -171,7 +203,7 @@
                 do {
                     LY_ARRAY_COUNT_TYPE u;
                     LY_ARRAY_FOR(schema->when, u) {
-                        ret = lyd_validate_when(tree, node, schema->when[u]);
+                        ret = lyd_validate_when(tree, node, schema->when[u], diff);
                         if (ret) {
                             break;
                         }
@@ -295,10 +327,11 @@
  *
  * @param[in,out] first First sibling to search in, is updated if needed.
  * @param[in] choic Choice node whose cases to check.
+ * @param[in,out] diff Validation diff.
  * @return LY_ERR value.
  */
 static LY_ERR
-lyd_validate_cases(struct lyd_node **first, const struct lysc_node_choice *choic)
+lyd_validate_cases(struct lyd_node **first, const struct lysc_node_choice *choic, struct lyd_node **diff)
 {
     const struct lysc_node *scase, *iter, *old_case = NULL, *new_case = NULL;
     struct lyd_node *match, *to_del;
@@ -352,7 +385,12 @@
             if (LYD_DEL_IS_ROOT(*first, to_del)) {
                 *first = (*first)->next;
             }
+            /* free previous node */
             lyd_free_tree(to_del);
+            if (diff) {
+                /* add into diff */
+                LY_CHECK_RET(lyd_val_diff_add(match, LYD_DIFF_OP_DELETE, diff));
+            }
             to_del = match;
         }
         if (LYD_DEL_IS_ROOT(*first, to_del)) {
@@ -403,11 +441,12 @@
  * @param[in,out] first First sibling to search in, is updated if needed.
  * @param[in] node Data node instance to check.
  * @param[in,out] next_p Temporary LY_LIST_FOR_SAFE next pointer, is updated if needed.
+ * @param[in,out] diff Validation diff.
  */
 static void
-lyd_validate_autodel_dup(struct lyd_node **first, struct lyd_node *node, struct lyd_node **next_p)
+lyd_validate_autodel_dup(struct lyd_node **first, struct lyd_node *node, struct lyd_node **next_p, struct lyd_node **diff)
 {
-    struct lyd_node *match, *next;
+    struct lyd_node *match, *next, *iter;
 
     if (lyd_val_has_default(node->schema)) {
         assert(node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CONTAINER));
@@ -427,6 +466,17 @@
                 if (match == *next_p) {
                     *next_p = (*next_p)->next;
                 }
+                if (diff) {
+                    /* add into diff */
+                    if ((match->schema->nodetype == LYS_CONTAINER) && !(match->schema->flags & LYS_PRESENCE)) {
+                        /* we do not want to track NP container changes, but remember any removed children */
+                        LY_LIST_FOR(LYD_CHILD(match), iter) {
+                            lyd_val_diff_add(iter, LYD_DIFF_OP_DELETE, diff);
+                        }
+                    } else {
+                        lyd_val_diff_add(match, LYD_DIFF_OP_DELETE, diff);
+                    }
+                }
                 lyd_free_tree(match);
 
                 /* remove only a single container/leaf default instance, if there are more, it is an error */
@@ -441,7 +491,8 @@
 }
 
 LY_ERR
-lyd_validate_new(struct lyd_node **first, const struct lysc_node *sparent, const struct lys_module *mod)
+lyd_validate_new(struct lyd_node **first, const struct lysc_node *sparent, const struct lys_module *mod,
+                 struct lyd_node **diff)
 {
     struct lyd_node *next, *node;
     const struct lysc_node *snode = NULL;
@@ -451,7 +502,7 @@
     while (*first && (snode = lys_getnext(snode, sparent, mod ? mod->compiled : NULL, LYS_GETNEXT_WITHCHOICE))) {
         /* check case duplicites */
         if (snode->nodetype == LYS_CHOICE) {
-            LY_CHECK_RET(lyd_validate_cases(first, (struct lysc_node_choice *)snode));
+            LY_CHECK_RET(lyd_validate_cases(first, (struct lysc_node_choice *)snode, diff));
         }
     }
 
@@ -467,7 +518,7 @@
         }
 
         /* remove old default(s) if it exists */
-        lyd_validate_autodel_dup(first, node, &next);
+        lyd_validate_autodel_dup(first, node, &next, diff);
 
         /* then check new node instance duplicities */
         LY_CHECK_RET(lyd_validate_duplicates(*first, node));
@@ -968,7 +1019,8 @@
 }
 
 LY_ERR
-lyd_validate_final_r(struct lyd_node *first, const struct lysc_node *sparent, const struct lys_module *mod, int val_opts, LYD_VALIDATE_OP op)
+lyd_validate_final_r(struct lyd_node *first, const struct lysc_node *sparent, const struct lys_module *mod, int val_opts,
+                     LYD_VALIDATE_OP op)
 {
     struct lyd_node *next = NULL, *node;
     const struct lysc_node *snode;
@@ -1039,7 +1091,8 @@
 
 LY_ERR
 lyd_validate_defaults_r(struct lyd_node *parent, struct lyd_node **first, const struct lysc_node *sparent,
-                        const struct lys_module *mod, struct ly_set *node_types, struct ly_set *node_when, int val_opts)
+                        const struct lys_module *mod, struct ly_set *node_types, struct ly_set *node_when, int val_opts,
+                        struct lyd_node **diff)
 {
     LY_ERR ret;
     const struct lysc_node *iter = NULL;
@@ -1063,7 +1116,7 @@
             if (((struct lysc_node_choice *)iter)->dflt && !lys_getnext_data(NULL, *first, NULL, iter, NULL)) {
                 /* create default case data */
                 LY_CHECK_RET(lyd_validate_defaults_r(parent, first, (struct lysc_node *)((struct lysc_node_choice *)iter)->dflt,
-                                                     NULL, node_types, node_when, val_opts));
+                                                     NULL, node_types, node_when, val_opts, diff));
             }
             break;
         case LYS_CONTAINER:
@@ -1079,7 +1132,8 @@
                 }
 
                 /* create any default children */
-                LY_CHECK_RET(lyd_validate_defaults_r(node, lyd_node_children_p(node), NULL, NULL, node_types, node_when, val_opts));
+                LY_CHECK_RET(lyd_validate_defaults_r(node, lyd_node_children_p(node), NULL, NULL, node_types, node_when,
+                                                     val_opts, diff));
             }
             break;
         case LYS_LEAF:
@@ -1099,6 +1153,10 @@
                     /* remember to resolve when */
                     ly_set_add(node_when, node, LY_SET_OPT_USEASLIST);
                 }
+                if (diff) {
+                    /* add into diff */
+                    LY_CHECK_RET(lyd_val_diff_add(node, LYD_DIFF_OP_CREATE, diff));
+                }
             }
             break;
         case LYS_LEAFLIST:
@@ -1120,6 +1178,10 @@
                         /* remember to resolve when */
                         ly_set_add(node_when, node, LY_SET_OPT_USEASLIST);
                     }
+                    if (diff) {
+                        /* add into diff */
+                        LY_CHECK_RET(lyd_val_diff_add(node, LYD_DIFF_OP_CREATE, diff));
+                    }
                 }
             }
             break;
@@ -1140,11 +1202,12 @@
  * @param[in,out] type_meta_check Set for unres metadata types.
  * @param[in,out] when_check Set for nodes with when conditions.
  * @param[in] val_opts Validation options, see @ref datavalidationoptions.
+ * @param[in,out] diff Validation diff.
  * @return LY_ERR value.
  */
 static LY_ERR
 lyd_validate_subtree(struct lyd_node *root, struct ly_set *type_check, struct ly_set *type_meta_check,
-                     struct ly_set *when_check, int val_opts)
+                     struct ly_set *when_check, int val_opts, struct lyd_node **diff)
 {
     const struct lyd_meta *meta;
     struct lyd_node *next, *node;
@@ -1162,11 +1225,11 @@
                 ly_set_add(type_check, (void *)node, LY_SET_OPT_USEASLIST);
             } else if (node->schema->nodetype & LYD_NODE_INNER) {
                 /* new node validation, autodelete */
-                LY_CHECK_RET(lyd_validate_new(lyd_node_children_p((struct lyd_node *)node), node->schema, NULL));
+                LY_CHECK_RET(lyd_validate_new(lyd_node_children_p((struct lyd_node *)node), node->schema, NULL, diff));
 
                 /* add nested defaults */
                 LY_CHECK_RET(lyd_validate_defaults_r(node, lyd_node_children_p((struct lyd_node *)node), NULL, NULL, type_check,
-                                                     when_check, val_opts));
+                                                     when_check, val_opts, diff));
             }
 
             if (!(node->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) && node->schema->when) {
@@ -1189,10 +1252,12 @@
  * @param[in] mod_count Count of @p modules.
  * @param[in] ly_ctx libyang context.
  * @param[in] val_opts Validation options, see @ref datavalidationoptions.
+ * @param[out] diff Generated validation diff, not generated if NULL.
  * @return LY_ERR value.
  */
 static LY_ERR
-_lyd_validate(struct lyd_node **tree, const struct lys_module *module, const struct ly_ctx *ctx, int val_opts)
+_lyd_validate(struct lyd_node **tree, const struct lys_module *module, const struct ly_ctx *ctx, int val_opts,
+              struct lyd_node **diff)
 {
     LY_ERR ret = LY_SUCCESS;
     struct lyd_node *first, *next, **first2;
@@ -1201,6 +1266,9 @@
     uint32_t i = 0;
 
     LY_CHECK_ARG_RET(NULL, tree, *tree || ctx || module, LY_EINVAL);
+    if (diff) {
+        *diff = NULL;
+    }
 
     next = *tree;
     while (1) {
@@ -1220,22 +1288,27 @@
         }
 
         /* validate new top-level nodes of this module, autodelete */
-        LY_CHECK_GOTO(ret = lyd_validate_new(first2, NULL, mod), cleanup);
+        ret = lyd_validate_new(first2, NULL, mod, diff);
+        LY_CHECK_GOTO(ret, cleanup);
 
         /* add all top-level defaults for this module */
-        LY_CHECK_GOTO(ret = lyd_validate_defaults_r(NULL, first2, NULL, mod, &type_check, &when_check, val_opts), cleanup);
+        ret = lyd_validate_defaults_r(NULL, first2, NULL, mod, &type_check, &when_check, val_opts, diff);
+        LY_CHECK_GOTO(ret, cleanup);
 
         /* process nested nodes */
         LY_LIST_FOR(*first2, first) {
-            LY_CHECK_GOTO(ret = lyd_validate_subtree(first, &type_check, &type_meta_check, &when_check, val_opts), cleanup);
+            ret = lyd_validate_subtree(first, &type_check, &type_meta_check, &when_check, val_opts, diff);
+            LY_CHECK_GOTO(ret, cleanup);
         }
 
         /* finish incompletely validated terminal values/attributes and when conditions */
-        ret = lyd_validate_unres(tree, &when_check, &type_check, &type_meta_check, LYD_JSON, lydjson_resolve_prefix, NULL);
+        ret = lyd_validate_unres(tree, &when_check, &type_check, &type_meta_check, LYD_JSON, lydjson_resolve_prefix,
+                                 NULL, diff);
         LY_CHECK_GOTO(ret, cleanup);
 
         /* perform final validation that assumes the data tree is final */
-        LY_CHECK_GOTO(ret = lyd_validate_final_r(*first2, NULL, mod, val_opts, 0), cleanup);
+        ret = lyd_validate_final_r(*first2, NULL, mod, val_opts, 0);
+        LY_CHECK_GOTO(ret, cleanup);
     }
 
 cleanup:
@@ -1246,15 +1319,15 @@
 }
 
 API LY_ERR
-lyd_validate(struct lyd_node **tree, const struct ly_ctx *ctx, int val_opts)
+lyd_validate(struct lyd_node **tree, const struct ly_ctx *ctx, int val_opts, struct lyd_node **diff)
 {
-    return _lyd_validate(tree, NULL, ctx, val_opts);
+    return _lyd_validate(tree, NULL, ctx, val_opts, diff);
 }
 
 API LY_ERR
-lyd_validate_module(struct lyd_node **tree, const struct lys_module *module, int val_opts)
+lyd_validate_module(struct lyd_node **tree, const struct lys_module *module, int val_opts, struct lyd_node **diff)
 {
-    return _lyd_validate(tree, module, NULL, val_opts);
+    return _lyd_validate(tree, module, NULL, val_opts, diff);
 }
 
 /**
@@ -1309,7 +1382,7 @@
 }
 
 API LY_ERR
-lyd_validate_op(struct lyd_node *op_tree, const struct lyd_node *tree, LYD_VALIDATE_OP op)
+lyd_validate_op(struct lyd_node *op_tree, const struct lyd_node *tree, LYD_VALIDATE_OP op, struct lyd_node **diff)
 {
     LY_ERR ret;
     struct lyd_node *tree_sibling, *op_subtree, *op_next, *op_node, *op_parent;
@@ -1317,6 +1390,9 @@
 
     LY_CHECK_ARG_RET(NULL, op_tree, !op_tree->parent, !tree || !tree->parent,
                      (op == LYD_VALIDATE_OP_NOTIF) || (op == LYD_VALIDATE_OP_RPC) || (op == LYD_VALIDATE_OP_REPLY), LY_EINVAL);
+    if (diff) {
+        *diff = NULL;
+    }
 
     /* find the operation/notification */
     LYD_TREE_DFS_BEGIN(op_tree, op_next, op_node) {
@@ -1354,11 +1430,11 @@
     }
 
     /* prevalidate whole operation subtree */
-    LY_CHECK_GOTO(ret = lyd_validate_subtree(op_node, &type_check, &type_meta_check, &when_check, 0), cleanup);
+    LY_CHECK_GOTO(ret = lyd_validate_subtree(op_node, &type_check, &type_meta_check, &when_check, 0, diff), cleanup);
 
     /* finish incompletely validated terminal values/attributes and when conditions on the full tree */
     LY_CHECK_GOTO(ret = lyd_validate_unres((struct lyd_node **)&tree, &when_check, &type_check, &type_meta_check,
-                                           LYD_JSON, lydjson_resolve_prefix, NULL), cleanup);
+                                           LYD_JSON, lydjson_resolve_prefix, NULL, diff), cleanup);
 
     /* perform final validation of the operation/notification */
     lyd_validate_obsolete(op_node);
diff --git a/src/validation.h b/src/validation.h
index 35492af..d6d1f17 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -31,10 +31,11 @@
  * @param[in] format Format of the unresolved data.
  * @param[in] get_prefix_clb Format-specific getter to resolve prefixes.
  * @param[in] parser_data Parser's data for @p get_prefix_clb.
+ * @param[in,out] diff Validation diff.
  * @return LY_ERR value.
  */
 LY_ERR lyd_validate_unres(struct lyd_node **tree, struct ly_set *node_when, struct ly_set *node_types, struct ly_set *meta_types,
-                          LYD_FORMAT format, ly_clb_resolve_prefix get_prefix_clb, void *parser_data);
+                          LYD_FORMAT format, ly_clb_resolve_prefix get_prefix_clb, void *parser_data, struct lyd_node **diff);
 
 /**
  * @brief Validate new siblings. Specifically, check duplicated instances, autodelete default values and cases.
@@ -44,9 +45,11 @@
  * @param[in,out] first First sibling.
  * @param[in] sparent Schema parent of the siblings, NULL for top-level siblings.
  * @param[in] mod Module of the siblings, NULL for nested siblings.
+ * @param[in,out] diff Validation diff.
  * @return LY_ERR value.
  */
-LY_ERR lyd_validate_new(struct lyd_node **first, const struct lysc_node *sparent, const struct lys_module *mod);
+LY_ERR lyd_validate_new(struct lyd_node **first, const struct lysc_node *sparent, const struct lys_module *mod,
+                        struct lyd_node **diff);
 
 /**
  * @brief Perform all remaining validation tasks, the data tree must be final when calling this function.
@@ -71,9 +74,11 @@
  * @param[in] node_types Set to add nodes with unresolved types into.
  * @param[in] node_when Set to add nodes with "when" conditions into.
  * @param[in] val_opts Validation options (@ref datavalidationoptions).
+ * @param[in,out] diff Validation diff.
  * @return LY_ERR value.
  */
 LY_ERR lyd_validate_defaults_r(struct lyd_node *parent, struct lyd_node **first, const struct lysc_node *sparent,
-                               const struct lys_module *mod, struct ly_set *node_types, struct ly_set *node_when, int val_opts);
+                               const struct lys_module *mod, struct ly_set *node_types, struct ly_set *node_when,
+                               int val_opts, struct lyd_node **diff);
 
 #endif /* LY_VALIDATION_H_ */
diff --git a/tests/utests/data/test_diff.c b/tests/utests/data/test_diff.c
index a282659..612bf88 100644
--- a/tests/utests/data/test_diff.c
+++ b/tests/utests/data/test_diff.c
@@ -842,7 +842,7 @@
     assert_non_null(mod);
 
     st->first = NULL;
-    assert_int_equal(lyd_validate_module(&st->first, mod, 0), LY_SUCCESS);
+    assert_int_equal(lyd_validate_module(&st->first, mod, 0, NULL), LY_SUCCESS);
     assert_ptr_not_equal(st->first, NULL);
     assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(st->ctx, xml2, LYD_XML, 0, LYD_VALIDATE_PRESENT, &st->second));
     assert_non_null(st->second);
diff --git a/tests/utests/data/test_merge.c b/tests/utests/data/test_merge.c
index 0c77cea..4ad6c9f 100644
--- a/tests/utests/data/test_merge.c
+++ b/tests/utests/data/test_merge.c
@@ -282,7 +282,7 @@
 
     /* merge them */
     assert_int_equal(lyd_merge(&st->target, st->source, 0), LY_SUCCESS);
-    assert_int_equal(lyd_validate(&st->target, NULL, LYD_VALIDATE_PRESENT), LY_SUCCESS);
+    assert_int_equal(lyd_validate(&st->target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
 
     /* check the result */
     lyd_print_mem(&printed, st->target, LYD_XML, LYD_PRINT_WITHSIBLINGS);
@@ -324,7 +324,7 @@
 
     /* merge them */
     assert_int_equal(lyd_merge(&st->target, st->source, 0), LY_SUCCESS);
-    assert_int_equal(lyd_validate(&st->target, NULL, LYD_VALIDATE_PRESENT), LY_SUCCESS);
+    assert_int_equal(lyd_validate(&st->target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
 
     /* check the result */
     lyd_print_mem(&printed, st->target, LYD_XML, LYD_PRINT_WITHSIBLINGS);
@@ -394,7 +394,7 @@
 
     /* merge them */
     assert_int_equal(lyd_merge(&st->target, st->source, LYD_MERGE_EXPLICIT), LY_SUCCESS);
-    assert_int_equal(lyd_validate(&st->target, NULL, LYD_VALIDATE_PRESENT), LY_SUCCESS);
+    assert_int_equal(lyd_validate(&st->target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
 
     /* check the result */
     lyd_print_mem(&printed, st->target, LYD_XML, LYD_PRINT_WITHSIBLINGS);
@@ -473,7 +473,7 @@
 
     /* merge them */
     assert_int_equal(lyd_merge(&st->target, st->source, LYD_MERGE_EXPLICIT), LY_SUCCESS);
-    assert_int_equal(lyd_validate(&st->target, NULL, LYD_VALIDATE_PRESENT), LY_SUCCESS);
+    assert_int_equal(lyd_validate(&st->target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
 
     /* check the result */
     lyd_print_mem(&printed, st->target, LYD_XML, LYD_PRINT_WITHSIBLINGS);
@@ -531,7 +531,7 @@
 
     /* merge them */
     assert_int_equal(lyd_merge(&st->target, st->source, 0), LY_SUCCESS);
-    assert_int_equal(lyd_validate(&st->target, NULL, LYD_VALIDATE_PRESENT), LY_SUCCESS);
+    assert_int_equal(lyd_validate(&st->target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
 
     /* check the result */
     lyd_print_mem(&printed, st->target, LYD_XML, LYD_PRINT_WITHSIBLINGS);
@@ -566,13 +566,13 @@
 
     st->target = lyd_new_path(NULL, st->ctx, "/merge-dflt:top/c", "c_dflt", 0);
     assert_non_null(st->target);
-    assert_int_equal(lyd_validate(&(st->target), NULL, LYD_VALIDATE_PRESENT), LY_SUCCESS);
+    assert_int_equal(lyd_validate(&(st->target), NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
 
     st->source = lyd_new_path(NULL, st->ctx, "/merge-dflt:top/a", "a_val", 0);
     assert_non_null(st->source);
     tmp = lyd_new_path(st->source, st->ctx, "/merge-dflt:top/b", "b_val", 0);
     assert_non_null(tmp);
-    assert_int_equal(lyd_validate(&(st->source), NULL, LYD_VALIDATE_PRESENT), LY_SUCCESS);
+    assert_int_equal(lyd_validate(&(st->source), NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
 
     assert_int_equal(lyd_merge(&st->target, st->source, LYD_MERGE_DESTRUCT), LY_SUCCESS);
     st->source = NULL;
@@ -608,13 +608,13 @@
 
     st->target = lyd_new_path(NULL, st->ctx, "/merge-dflt:top/c", "c_dflt", 0);
     assert_non_null(st->target);
-    assert_int_equal(lyd_validate(&(st->target), NULL, LYD_VALIDATE_PRESENT), LY_SUCCESS);
+    assert_int_equal(lyd_validate(&(st->target), NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
 
     st->source = lyd_new_path(NULL, st->ctx, "/merge-dflt:top/a", "a_val", 0);
     assert_non_null(st->source);
     tmp = lyd_new_path(st->source, st->ctx, "/merge-dflt:top/b", "b_val", 0);
     assert_non_null(tmp);
-    assert_int_equal(lyd_validate(&(st->source), NULL, LYD_VALIDATE_PRESENT), LY_SUCCESS);
+    assert_int_equal(lyd_validate(&(st->source), NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
 
     assert_int_equal(lyd_merge(&st->target, st->source, LYD_MERGE_EXPLICIT), LY_SUCCESS);
 
diff --git a/tests/utests/data/test_validation.c b/tests/utests/data/test_validation.c
index 4bcd777..da68a40 100644
--- a/tests/utests/data/test_validation.c
+++ b/tests/utests/data/test_validation.c
@@ -1019,7 +1019,7 @@
     *state = test_defaults;
 
     char *str;
-    struct lyd_node *tree, *node;
+    struct lyd_node *tree, *node, *diff;
     const struct lys_module *mod = ly_ctx_get_module_latest(ctx, "f");
 
     struct ly_out *out;
@@ -1027,8 +1027,9 @@
 
     /* get defaults */
     tree = NULL;
-    assert_int_equal(lyd_validate_module(&tree, mod, 0), LY_SUCCESS);
+    assert_int_equal(lyd_validate_module(&tree, mod, 0, &diff), LY_SUCCESS);
     assert_non_null(tree);
+    assert_non_null(diff);
 
     /* check all defaults exist */
     lyd_print(out, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_IMPL_TAG);
@@ -1049,11 +1050,32 @@
         "</cont>");
     ly_out_reset(out);
 
+    /* check diff */
+    lyd_print(out, diff, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_ALL);
+    assert_string_equal(str,
+        "<ll1 xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"create\">def1</ll1>"
+        "<ll1 xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"create\">def2</ll1>"
+        "<ll1 xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"create\">def3</ll1>"
+        "<d xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"create\">15</d>"
+        "<ll2 xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"create\">dflt1</ll2>"
+        "<ll2 xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"create\">dflt2</ll2>"
+        "<cont xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">"
+            "<ll1 yang:operation=\"create\">def1</ll1>"
+            "<ll1 yang:operation=\"create\">def2</ll1>"
+            "<ll1 yang:operation=\"create\">def3</ll1>"
+            "<d yang:operation=\"create\">15</d>"
+            "<ll2 yang:operation=\"create\">dflt1</ll2>"
+            "<ll2 yang:operation=\"create\">dflt2</ll2>"
+        "</cont>"
+        );
+    ly_out_reset(out);
+    lyd_free_siblings(diff);
+
     /* create another explicit case and validate */
     node = lyd_new_term(NULL, mod, "l", "value");
     assert_non_null(node);
     assert_int_equal(lyd_insert_sibling(tree, node), LY_SUCCESS);
-    assert_int_equal(lyd_validate(&tree, ctx, LYD_VALIDATE_PRESENT), LY_SUCCESS);
+    assert_int_equal(lyd_validate(&tree, ctx, LYD_VALIDATE_PRESENT, &diff), LY_SUCCESS);
 
     /* check data tree */
     lyd_print(out, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_IMPL_TAG);
@@ -1072,6 +1094,16 @@
         "<l xmlns=\"urn:tests:f\">value</l>");
     ly_out_reset(out);
 
+    /* check diff */
+    lyd_print(out, diff, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_ALL);
+    assert_string_equal(str,
+        "<ll1 xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"delete\">def1</ll1>"
+        "<ll1 xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"delete\">def2</ll1>"
+        "<ll1 xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"delete\">def3</ll1>"
+        );
+    ly_out_reset(out);
+    lyd_free_siblings(diff);
+
     /* create explicit leaf-list and leaf and validate */
     node = lyd_new_term(NULL, mod, "d", "15");
     assert_non_null(node);
@@ -1079,7 +1111,7 @@
     node = lyd_new_term(NULL, mod, "ll2", "dflt2");
     assert_non_null(node);
     assert_int_equal(lyd_insert_sibling(tree, node), LY_SUCCESS);
-    assert_int_equal(lyd_validate(&tree, ctx, LYD_VALIDATE_PRESENT), LY_SUCCESS);
+    assert_int_equal(lyd_validate(&tree, ctx, LYD_VALIDATE_PRESENT, &diff), LY_SUCCESS);
 
     /* check data tree */
     lyd_print(out, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_IMPL_TAG);
@@ -1097,12 +1129,22 @@
         "<ll2 xmlns=\"urn:tests:f\">dflt2</ll2>");
     ly_out_reset(out);
 
+    /* check diff */
+    lyd_print(out, diff, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_ALL);
+    assert_string_equal(str,
+        "<d xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"delete\">15</d>"
+        "<ll2 xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"delete\">dflt1</ll2>"
+        "<ll2 xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"delete\">dflt2</ll2>"
+        );
+    ly_out_reset(out);
+    lyd_free_siblings(diff);
+
     /* create first explicit container, which should become implicit */
     node = lyd_new_inner(NULL, mod, "cont");
     assert_non_null(node);
     assert_int_equal(lyd_insert_before(tree, node), LY_SUCCESS);
     tree = tree->prev;
-    assert_int_equal(lyd_validate(&tree, ctx, LYD_VALIDATE_PRESENT), LY_SUCCESS);
+    assert_int_equal(lyd_validate(&tree, ctx, LYD_VALIDATE_PRESENT, &diff), LY_SUCCESS);
 
     /* check data tree */
     lyd_print(out, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_IMPL_TAG);
@@ -1120,11 +1162,14 @@
         "<ll2 xmlns=\"urn:tests:f\">dflt2</ll2>");
     ly_out_reset(out);
 
+    /* check diff */
+    assert_null(diff);
+
     /* create second explicit container, which should become implicit, so the first tree node should be removed */
     node = lyd_new_inner(NULL, mod, "cont");
     assert_non_null(node);
     assert_int_equal(lyd_insert_after(tree, node), LY_SUCCESS);
-    assert_int_equal(lyd_validate(&tree, ctx, LYD_VALIDATE_PRESENT), LY_SUCCESS);
+    assert_int_equal(lyd_validate(&tree, ctx, LYD_VALIDATE_PRESENT, &diff), LY_SUCCESS);
 
     /* check data tree */
     lyd_print(out, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_IMPL_TAG);
@@ -1142,11 +1187,14 @@
         "<ll2 xmlns=\"urn:tests:f\">dflt2</ll2>");
     ly_out_reset(out);
 
+    /* check diff */
+    assert_null(diff);
+
     /* similar changes for nested defaults */
     assert_non_null(lyd_new_term(tree, NULL, "ll1", "def3"));
     assert_non_null(lyd_new_term(tree, NULL, "d", "5"));
     assert_non_null(lyd_new_term(tree, NULL, "ll2", "non-dflt"));
-    assert_int_equal(lyd_validate(&tree, ctx, LYD_VALIDATE_PRESENT), LY_SUCCESS);
+    assert_int_equal(lyd_validate(&tree, ctx, LYD_VALIDATE_PRESENT, &diff), LY_SUCCESS);
 
     /* check data tree */
     lyd_print(out, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_IMPL_TAG);
@@ -1161,6 +1209,21 @@
         "<ll2 xmlns=\"urn:tests:f\">dflt2</ll2>");
     ly_out_reset(out);
 
+    /* check diff */
+    lyd_print(out, diff, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_ALL);
+    assert_string_equal(str,
+        "<cont xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">"
+            "<ll1 yang:operation=\"delete\">def1</ll1>"
+            "<ll1 yang:operation=\"delete\">def2</ll1>"
+            "<ll1 yang:operation=\"delete\">def3</ll1>"
+            "<d yang:operation=\"delete\">15</d>"
+            "<ll2 yang:operation=\"delete\">dflt1</ll2>"
+            "<ll2 yang:operation=\"delete\">dflt2</ll2>"
+        "</cont>"
+        );
+    ly_out_reset(out);
+    lyd_free_siblings(diff);
+
     lyd_free_siblings(tree);
     ly_out_free(out, NULL, 1);
 
@@ -1178,7 +1241,7 @@
 
     /* get empty data */
     tree = NULL;
-    assert_int_equal(lyd_validate_module(&tree, mod, 0), LY_SUCCESS);
+    assert_int_equal(lyd_validate_module(&tree, mod, 0, NULL), LY_SUCCESS);
     assert_null(tree);
 
     /* disabled by f1 */
@@ -1194,7 +1257,7 @@
     assert_int_equal(lys_feature_enable(mod, "f1"), LY_SUCCESS);
 
     /* get data with default container */
-    assert_int_equal(lyd_validate_module(&tree, mod, 0), LY_SUCCESS);
+    assert_int_equal(lyd_validate_module(&tree, mod, 0, NULL), LY_SUCCESS);
     assert_non_null(tree);
     lyd_free_siblings(tree);
 
@@ -1256,17 +1319,17 @@
     assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_XML, LYD_PARSE_ONLY, 0, &tree));
     assert_non_null(tree);
 
-    assert_int_equal(LY_EVALID, lyd_validate(&tree, NULL, LYD_VALIDATE_PRESENT));
+    assert_int_equal(LY_EVALID, lyd_validate(&tree, NULL, LYD_VALIDATE_PRESENT, NULL));
     logbuf_assert("Data are disabled by \"cont\" schema node if-feature. /g:cont");
 
     assert_int_equal(lys_feature_enable(mod, "f1"), LY_SUCCESS);
 
-    assert_int_equal(LY_EVALID, lyd_validate(&tree, NULL, LYD_VALIDATE_PRESENT));
+    assert_int_equal(LY_EVALID, lyd_validate(&tree, NULL, LYD_VALIDATE_PRESENT, NULL));
     logbuf_assert("Data are disabled by \"b\" schema node if-feature. /g:cont/l");
 
     assert_int_equal(lys_feature_enable(mod, "f2"), LY_SUCCESS);
 
-    assert_int_equal(LY_SUCCESS, lyd_validate(&tree, NULL, LYD_VALIDATE_PRESENT));
+    assert_int_equal(LY_SUCCESS, lyd_validate(&tree, NULL, LYD_VALIDATE_PRESENT, NULL));
 
     lyd_free_siblings(tree);
 
@@ -1298,7 +1361,7 @@
     assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_XML, LYD_PARSE_ONLY, 0, &tree));
     assert_non_null(tree);
 
-    assert_int_equal(LY_EVALID, lyd_validate(&tree, NULL, LYD_VALIDATE_PRESENT | LYD_VALIDATE_NO_STATE));
+    assert_int_equal(LY_EVALID, lyd_validate(&tree, NULL, LYD_VALIDATE_PRESENT | LYD_VALIDATE_NO_STATE, NULL));
     logbuf_assert("Invalid state data node \"cont2\" found. /h:cont/cont2");
 
     lyd_free_siblings(tree);
@@ -1359,7 +1422,7 @@
     assert_non_null(op_tree);
 
     /* missing leafref */
-    assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, NULL, LYD_VALIDATE_OP_RPC));
+    assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, NULL, LYD_VALIDATE_OP_RPC, NULL));
     logbuf_assert("Invalid leafref value \"target\" - no target instance \"/lf3\" with the same value."
         " /j:cont/l1[k='val1']/act/lf2");
     ly_in_free(in, 0);
@@ -1373,7 +1436,7 @@
     assert_non_null(tree);
 
     /* disabled if-feature */
-    assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, tree, LYD_VALIDATE_OP_RPC));
+    assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, tree, LYD_VALIDATE_OP_RPC, NULL));
     logbuf_assert("Data are disabled by \"act\" schema node if-feature. /j:cont/l1[k='val1']/act");
 
     mod = ly_ctx_get_module_latest(ctx, "j");
@@ -1381,7 +1444,7 @@
     assert_int_equal(LY_SUCCESS, lys_feature_enable(mod, "feat1"));
 
     /* input must false */
-    assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, tree, LYD_VALIDATE_OP_RPC));
+    assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, tree, LYD_VALIDATE_OP_RPC, NULL));
     logbuf_assert("Must condition \"../../lf1 = 'true'\" not satisfied. /j:cont/l1[k='val1']/act");
 
     lyd_free_siblings(tree);
@@ -1394,7 +1457,7 @@
     assert_non_null(tree);
 
     /* success */
-    assert_int_equal(LY_SUCCESS, lyd_validate_op(op_tree, tree, LYD_VALIDATE_OP_RPC));
+    assert_int_equal(LY_SUCCESS, lyd_validate_op(op_tree, tree, LYD_VALIDATE_OP_RPC, NULL));
 
     lys_feature_disable(mod, "feat1");
     lyd_free_tree(op_tree);
@@ -1435,7 +1498,7 @@
     ly_in_free(in, 0);
 
     /* missing leafref */
-    assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, NULL, LYD_VALIDATE_OP_REPLY));
+    assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, NULL, LYD_VALIDATE_OP_REPLY, NULL));
     logbuf_assert("Invalid leafref value \"target\" - no target instance \"/lf4\" with the same value."
         " /j:cont/l1[k='val1']/act/lf2");
 
@@ -1448,7 +1511,7 @@
     assert_non_null(tree);
 
     /* disabled if-feature */
-    assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, tree, LYD_VALIDATE_OP_REPLY));
+    assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, tree, LYD_VALIDATE_OP_REPLY, NULL));
     logbuf_assert("Data are disabled by \"act\" schema node if-feature. /j:cont/l1[k='val1']/act");
 
     mod = ly_ctx_get_module_latest(ctx, "j");
@@ -1456,7 +1519,7 @@
     assert_int_equal(LY_SUCCESS, lys_feature_enable(mod, "feat1"));
 
     /* input must false */
-    assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, tree, LYD_VALIDATE_OP_REPLY));
+    assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, tree, LYD_VALIDATE_OP_REPLY, NULL));
     logbuf_assert("Must condition \"../../lf1 = 'true2'\" not satisfied. /j:cont/l1[k='val1']/act");
 
     lyd_free_siblings(tree);
@@ -1469,7 +1532,7 @@
     assert_non_null(tree);
 
     /* success */
-    assert_int_equal(LY_SUCCESS, lyd_validate_op(op_tree, tree, LYD_VALIDATE_OP_REPLY));
+    assert_int_equal(LY_SUCCESS, lyd_validate_op(op_tree, tree, LYD_VALIDATE_OP_REPLY, NULL));
 
     lys_feature_disable(mod, "feat1");
     lyd_free_tree(op_tree);