MEDIUM: log-format: Use standard HAProxy log system to report errors

The function log format emit its own error message using Alert(). This
patch replaces this behavior and uses the standard HAProxy error system
(with memprintf).

The benefits are:
 - cleaning the log system

 - the logformat can ignore the caller (actually the caller must set
   a flag designing the caller function).

 - Make the usage of the logformat function easy for future components.
diff --git a/include/proto/log.h b/include/proto/log.h
index f5a4f3f..2d4ca84 100644
--- a/include/proto/log.h
+++ b/include/proto/log.h
@@ -67,14 +67,14 @@
 /*
  * add to the logformat linked list
  */
-int add_to_logformat_list(char *start, char *end, int type, struct list *list_format);
+int add_to_logformat_list(char *start, char *end, int type, struct list *list_format, char **err);
 
 /*
  * Parse the log_format string and fill a linked list.
  * Variable name are preceded by % and composed by characters [a-zA-Z0-9]* : %varname
  * You can set arguments using { } : %{many arguments}varname
  */
-int parse_logformat_string(const char *str, struct proxy *curproxy, struct list *list_format, int options, int cap);
+int parse_logformat_string(const char *str, struct proxy *curproxy, struct list *list_format, int options, int cap, char **err);
 /*
  * Displays the message on stderr with the date and pid. Overrides the quiet
  * mode during startup.
diff --git a/src/cfgparse.c b/src/cfgparse.c
index db1641e..fbd7364 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -7502,6 +7502,7 @@
 	int err_code = 0;
 	unsigned int next_pxid = 1;
 	struct bind_conf *bind_conf;
+	char *err;
 
 	bind_conf = NULL;
 	/*
@@ -7801,7 +7802,11 @@
 			curproxy->conf.args.ctx = ARGC_UBK;
 			curproxy->conf.args.file = rule->file;
 			curproxy->conf.args.line = rule->line;
-			if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR)) {
+			err = NULL;
+			if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
+				Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
+				      rule->file, rule->line, pxname, err);
+				free(err);
 				cfgerr++;
 				continue;
 			}
@@ -8288,8 +8293,12 @@
 			curproxy->conf.args.ctx = ARGC_LOG;
 			curproxy->conf.args.file = curproxy->conf.lfs_file;
 			curproxy->conf.args.line = curproxy->conf.lfs_line;
+			err = NULL;
 			if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
-			                            SMP_VAL_FE_LOG_END)) {
+			                            SMP_VAL_FE_LOG_END, &err)) {
+				Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
+				      curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
+				free(err);
 				cfgerr++;
 			}
 			curproxy->conf.args.file = NULL;
@@ -8300,10 +8309,17 @@
 			curproxy->conf.args.ctx = ARGC_LOGSD;
 			curproxy->conf.args.file = curproxy->conf.lfsd_file;
 			curproxy->conf.args.line = curproxy->conf.lfsd_line;
+			err = NULL;
 			if (!parse_logformat_string(curproxy->conf.logformat_sd_string, curproxy, &curproxy->logformat_sd, LOG_OPT_MANDATORY,
-			                            SMP_VAL_FE_LOG_END)) {
+			                            SMP_VAL_FE_LOG_END, &err)) {
+				Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
+				      curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
+				free(err);
 				cfgerr++;
-			} else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd)) {
+			} else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
+				Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
+				      curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
+				free(err);
 				cfgerr++;
 			}
 			curproxy->conf.args.file = NULL;
@@ -8314,8 +8330,12 @@
 			curproxy->conf.args.ctx = ARGC_UIF;
 			curproxy->conf.args.file = curproxy->conf.uif_file;
 			curproxy->conf.args.line = curproxy->conf.uif_line;
+			err = NULL;
 			if (!parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
-			                            (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR)) {
+			                            (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
+				Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
+				      curproxy->conf.uif_file, curproxy->conf.uif_line, err);
+				free(err);
 				cfgerr++;
 			}
 			curproxy->conf.args.file = NULL;
diff --git a/src/log.c b/src/log.c
index 9ec89b2..3a6f781 100644
--- a/src/log.c
+++ b/src/log.c
@@ -291,15 +291,17 @@
  * Parse args in a logformat_var. Returns 0 in error
  * case, otherwise, it returns 1.
  */
-int parse_logformat_var_args(char *args, struct logformat_node *node)
+int parse_logformat_var_args(char *args, struct logformat_node *node, char **err)
 {
 	int i = 0;
 	int end = 0;
 	int flags = 0;  // 1 = +  2 = -
 	char *sp = NULL; // start pointer
 
-	if (args == NULL)
+	if (args == NULL) {
+		memprintf(err, "internal error: parse_logformat_var_args() expects non null 'args'");
 		return 0;
+	}
 
 	while (1) {
 		if (*args == '\0')
@@ -345,7 +347,7 @@
  * ignored when arg_len is 0. Neither <var> nor <var_len> may be null.
  * Returns false in error case and err is filled, otherwise returns true.
  */
-int parse_logformat_var(char *arg, int arg_len, char *var, int var_len, struct proxy *curproxy, struct list *list_format, int *defoptions)
+int parse_logformat_var(char *arg, int arg_len, char *var, int var_len, struct proxy *curproxy, struct list *list_format, int *defoptions, char **err)
 {
 	int j;
 	struct logformat_node *node;
@@ -356,14 +358,14 @@
 			if (logformat_keywords[j].mode != PR_MODE_HTTP || curproxy->mode == PR_MODE_HTTP) {
 				node = calloc(1, sizeof(*node));
 				if (!node) {
-					Alert("Out of memory error.\n");
+					memprintf(err, "out of memory error");
 					return 0;
 				}
 				node->type = logformat_keywords[j].type;
 				node->options = *defoptions;
 				if (arg_len) {
 					node->arg = my_strndup(arg, arg_len);
-					if (!parse_logformat_var_args(node->arg, node))
+					if (!parse_logformat_var_args(node->arg, node, err))
 						return 0;
 				}
 				if (node->type == LOG_FMT_GLOBAL) {
@@ -384,9 +386,8 @@
 					        logformat_keywords[j].name, fmt_directive(curproxy), logformat_keywords[j].replace_by);
 				return 1;
 			} else {
-				Alert("parsing [%s:%d] : '%s' : format variable '%s' is reserved for HTTP mode.\n",
-				      curproxy->conf.args.file, curproxy->conf.args.line, fmt_directive(curproxy),
-				      logformat_keywords[j].name);
+				memprintf(err, "format variable '%s' is reserved for HTTP mode",
+				          logformat_keywords[j].name);
 				return 0;
 			}
 		}
@@ -394,8 +395,7 @@
 
 	j = var[var_len];
 	var[var_len] = 0;
-	Alert("parsing [%s:%d] : no such format variable '%s' in '%s'. If you wanted to emit the '%%' character verbatim, you need to use '%%%%' in log-format expressions.\n",
-	      curproxy->conf.args.file, curproxy->conf.args.line, var, fmt_directive(curproxy));
+	memprintf(err, "no such format variable '%s'. If you wanted to emit the '%%' character verbatim, you need to use '%%%%'", var);
 	var[var_len] = j;
 	return 0;
 }
@@ -411,14 +411,14 @@
  *  LOG_TEXT: copy chars from start to end excluding end.
  *
 */
-int add_to_logformat_list(char *start, char *end, int type, struct list *list_format)
+int add_to_logformat_list(char *start, char *end, int type, struct list *list_format, char **err)
 {
 	char *str;
 
 	if (type == LF_TEXT) { /* type text */
 		struct logformat_node *node = calloc(1, sizeof(*node));
 		if (!node) {
-			Alert("Out of memory error.\n");
+			memprintf(err, "out of memory error");
 			return 0;
 		}
 		str = calloc(1, end - start + 1);
@@ -430,7 +430,7 @@
 	} else if (type == LF_SEPARATOR) {
 		struct logformat_node *node = calloc(1, sizeof(*node));
 		if (!node) {
-			Alert("Out of memory error.\n");
+			memprintf(err, "out of memory error");
 			return 0;
 		}
 		node->type = LOG_FMT_SEPARATOR;
@@ -446,29 +446,26 @@
  *
  * In error case, the function returns 0, otherwise it returns 1.
  */
-int add_sample_to_logformat_list(char *text, char *arg, int arg_len, struct proxy *curpx, struct list *list_format, int options, int cap, const char *file, int line)
+int add_sample_to_logformat_list(char *text, char *arg, int arg_len, struct proxy *curpx, struct list *list_format, int options, int cap, char **err)
 {
 	char *cmd[2];
 	struct sample_expr *expr;
 	struct logformat_node *node;
 	int cmd_arg;
-	char *errmsg = NULL;
 
 	cmd[0] = text;
 	cmd[1] = "";
 	cmd_arg = 0;
 
-	expr = sample_parse_expr(cmd, &cmd_arg, file, line, &errmsg, &curpx->conf.args);
+	expr = sample_parse_expr(cmd, &cmd_arg, curpx->conf.args.file, curpx->conf.args.line, err, &curpx->conf.args);
 	if (!expr) {
-		Alert("parsing [%s:%d] : '%s' : sample fetch <%s> failed with : %s\n",
-		      curpx->conf.args.file, curpx->conf.args.line, fmt_directive(curpx),
-		      text, errmsg);
+		memprintf(err, "failed to parse sample expression <%s> : %s", text, *err);
 		return 0;
 	}
 
 	node = calloc(1, sizeof(*node));
 	if (!node) {
-		Alert("Out of memory error.\n");
+		memprintf(err, "out of memory error");
 		return 0;
 	}
 	node->type = LOG_FMT_EXPR;
@@ -477,7 +474,7 @@
 
 	if (arg_len) {
 		node->arg = my_strndup(arg, arg_len);
-		if (!parse_logformat_var_args(node->arg, node))
+		if (!parse_logformat_var_args(node->arg, node, err))
 			return 0;
 	}
 	if (expr->fetch->val & cap & SMP_VAL_REQUEST)
@@ -487,9 +484,8 @@
 		node->options |= LOG_OPT_RES_CAP; /* fetch method is response-compatible */
 
 	if (!(expr->fetch->val & cap)) {
-		Alert("parsing [%s:%d] : '%s' : sample fetch <%s> may not be reliably used here because it needs '%s' which is not available here.\n",
-		      curpx->conf.args.file, curpx->conf.args.line, fmt_directive(curpx),
-		      text, sample_src_names(expr->fetch->use));
+		memprintf(err, "sample fetch <%s> may not be reliably used here because it needs '%s' which is not available here",
+		          text, sample_src_names(expr->fetch->use));
 		return 0;
 	}
 
@@ -519,9 +515,9 @@
  *  options: LOG_OPT_* to force on every node
  *  cap: all SMP_VAL_* flags supported by the consumer
  *
- * The function returns 1 in success case, otherwise, it returns 0.
+ * The function returns 1 in success case, otherwise, it returns 0 and err is filled.
  */
-int parse_logformat_string(const char *fmt, struct proxy *curproxy, struct list *list_format, int options, int cap)
+int parse_logformat_string(const char *fmt, struct proxy *curproxy, struct list *list_format, int options, int cap, char **err)
 {
 	char *sp, *str, *backfmt; /* start pointer for text parts */
 	char *arg = NULL; /* start pointer for args */
@@ -534,7 +530,7 @@
 
 	sp = str = backfmt = strdup(fmt);
 	if (!str) {
-		Alert("Out of memory error.\n");
+		memprintf(err, "out of memory error");
 		return 0;
 	}
 	curproxy->to_log |= LW_INIT;
@@ -579,8 +575,8 @@
 				cformat = LF_TEXT;
 				pformat = LF_TEXT; /* finally we include the previous char as well */
 				sp = str - 1; /* send both the '%' and the current char */
-				Alert("parsing [%s:%d] : Unexpected variable name near '%c' at position %d in %s line : '%s'. Maybe you want to write a simgle '%%', use the syntax '%%%%'.\n",
-				      curproxy->conf.args.file, curproxy->conf.args.line, *str, (int)(str - backfmt), fmt_directive(curproxy), fmt);
+				memprintf(err, "unexpected variable name near '%c' at position %d line : '%s'. Maybe you want to write a simgle '%%', use the syntax '%%%%'",
+				          *str, (int)(str - backfmt), fmt);
 				return 0;
 
 			}
@@ -607,8 +603,7 @@
 				var = str;
 				break;
 			}
-			Alert("parsing [%s:%d] : Parse argument modifier without variable name, in '%s' near '%%{%s}'\n",
-			      curproxy->conf.args.file, curproxy->conf.args.line, fmt_directive(curproxy), arg);
+			memprintf(err, "parse argument modifier without variable name near '%%{%s}'", arg);
 			return 0;
 
 		case LF_STEXPR:                        // text immediately following '%['
@@ -641,17 +636,16 @@
 		if (cformat != pformat || pformat == LF_SEPARATOR) {
 			switch (pformat) {
 			case LF_VAR:
-				if (!parse_logformat_var(arg, arg_len, var, var_len, curproxy, list_format, &options))
+				if (!parse_logformat_var(arg, arg_len, var, var_len, curproxy, list_format, &options, err))
 					return 0;
 				break;
 			case LF_STEXPR:
-				if (!add_sample_to_logformat_list(var, arg, arg_len, curproxy, list_format, options, cap,
-				                             curproxy->conf.args.file, curproxy->conf.args.line))
+				if (!add_sample_to_logformat_list(var, arg, arg_len, curproxy, list_format, options, cap, err))
 					return 0;
 				break;
 			case LF_TEXT:
 			case LF_SEPARATOR:
-				if (!add_to_logformat_list(sp, str, pformat, list_format))
+				if (!add_to_logformat_list(sp, str, pformat, list_format, err))
 					return 0;
 				break;
 			}
@@ -660,9 +654,7 @@
 	}
 
 	if (pformat == LF_STARTVAR || pformat == LF_STARG || pformat == LF_STEXPR) {
-		Alert("parsing [%s:%d] : Truncated '%s' line after '%s'\n",
-		      curproxy->conf.args.file, curproxy->conf.args.line, fmt_directive(curproxy),
-		      var ? var : arg ? arg : "%");
+		memprintf(err, "truncated line after '%s'", var ? var : arg ? arg : "%");
 		return 0;
 	}
 	free(backfmt);
diff --git a/src/proto_http.c b/src/proto_http.c
index 725ea9c..6dfc8f9 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -9139,8 +9139,12 @@
 		LIST_INIT(&rule->arg.hdr_add.fmt);
 
 		proxy->conf.args.ctx = ARGC_HRQ;
+		error = NULL;
 		if (!parse_logformat_string(args[cur_arg + 1], proxy, &rule->arg.hdr_add.fmt, LOG_OPT_HTTP,
-		                            (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR)) {
+		                            (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &error)) {
+			Alert("parsing [%s:%d]: 'http-request %s': %s.\n",
+			      file, linenum, args[0], error);
+			free(error);
 			goto out_err;
 		}
 		free(proxy->conf.lfs_file);
@@ -9171,8 +9175,12 @@
 		}
 
 		proxy->conf.args.ctx = ARGC_HRQ;
+		error = NULL;
 		if (!parse_logformat_string(args[cur_arg + 2], proxy, &rule->arg.hdr_add.fmt, LOG_OPT_HTTP,
-		                            (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR)) {
+		                            (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &error)) {
+			Alert("parsing [%s:%d]: 'http-request %s': %s.\n",
+			      file, linenum, args[0], error);
+			free(error);
 			goto out_err;
 		}
 
@@ -9285,8 +9293,12 @@
 
 		LIST_INIT(&rule->arg.map.key);
 		proxy->conf.args.ctx = ARGC_HRQ;
+		error = NULL;
 		if (!parse_logformat_string(args[cur_arg], proxy, &rule->arg.map.key, LOG_OPT_HTTP,
-		                            (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR)) {
+		                            (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &error)) {
+			Alert("parsing [%s:%d]: 'http-request %s': %s.\n",
+			      file, linenum, args[0], error);
+			free(error);
 			goto out_err;
 		}
 		free(proxy->conf.lfs_file);
@@ -9313,8 +9325,12 @@
 
 		LIST_INIT(&rule->arg.map.key);
 		proxy->conf.args.ctx = ARGC_HRQ;
+		error = NULL;
 		if (!parse_logformat_string(args[cur_arg], proxy, &rule->arg.map.key, LOG_OPT_HTTP,
-		                            (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR)) {
+		                            (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &error)) {
+			Alert("parsing [%s:%d]: 'http-request %s': %s.\n",
+			      file, linenum, args[0], error);
+			free(error);
 			goto out_err;
 		}
 		free(proxy->conf.lfs_file);
@@ -9341,8 +9357,12 @@
 
 		LIST_INIT(&rule->arg.map.key);
 		proxy->conf.args.ctx = ARGC_HRQ;
+		error = NULL;
 		if (!parse_logformat_string(args[cur_arg], proxy, &rule->arg.map.key, LOG_OPT_HTTP,
-		                            (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR)) {
+		                            (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &error)) {
+			Alert("parsing [%s:%d]: 'http-request %s': %s.\n",
+			      file, linenum, args[0], error);
+			free(error);
 			goto out_err;
 		}
 		free(proxy->conf.lfs_file);
@@ -9372,14 +9392,22 @@
 		proxy->conf.args.ctx = ARGC_HRQ;
 
 		/* key pattern */
+		error = NULL;
 		if (!parse_logformat_string(args[cur_arg], proxy, &rule->arg.map.key, LOG_OPT_HTTP,
-		                            (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR)) {
+		                            (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &error)) {
+			Alert("parsing [%s:%d]: 'http-request %s' key: %s.\n",
+			      file, linenum, args[0], error);
+			free(error);
 			goto out_err;
 		}
 
 		/* value pattern */
+		error = NULL;
 		if (!parse_logformat_string(args[cur_arg + 1], proxy, &rule->arg.map.value, LOG_OPT_HTTP,
-		                            (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR)) {
+		                            (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &error)) {
+			Alert("parsing [%s:%d]: 'http-request %s' pattern: %s.\n",
+			      file, linenum, args[0], error);
+			free(error);
 			goto out_err;
 		}
 		free(proxy->conf.lfs_file);
@@ -9551,8 +9579,12 @@
 		LIST_INIT(&rule->arg.hdr_add.fmt);
 
 		proxy->conf.args.ctx = ARGC_HRS;
+		error = NULL;
 		if (!parse_logformat_string(args[cur_arg + 1], proxy, &rule->arg.hdr_add.fmt, LOG_OPT_HTTP,
-		                            (proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR)) {
+		                            (proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR, &error)) {
+			Alert("parsing [%s:%d]: 'http-response %s': %s.\n",
+			      file, linenum, args[0], error);
+			free(error);
 			goto out_err;
 		}
 		free(proxy->conf.lfs_file);
@@ -9583,8 +9615,12 @@
 		}
 
 		proxy->conf.args.ctx = ARGC_HRQ;
+		error = NULL;
 		if (!parse_logformat_string(args[cur_arg + 2], proxy, &rule->arg.hdr_add.fmt, LOG_OPT_HTTP,
-		                            (proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR)) {
+		                            (proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR, &error)) {
+			Alert("parsing [%s:%d]: 'http-response %s': %s.\n",
+			      file, linenum, args[0], error);
+			free(error);
 			goto out_err;
 		}
 
@@ -9631,8 +9667,12 @@
 
 		LIST_INIT(&rule->arg.map.key);
 		proxy->conf.args.ctx = ARGC_HRS;
+		error = NULL;
 		if (!parse_logformat_string(args[cur_arg], proxy, &rule->arg.map.key, LOG_OPT_HTTP,
-		                            (proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR)) {
+		                            (proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR, &error)) {
+			Alert("parsing [%s:%d]: 'http-response %s': %s.\n",
+			      file, linenum, args[0], error);
+			free(error);
 			goto out_err;
 		}
 		free(proxy->conf.lfs_file);
@@ -9660,8 +9700,12 @@
 
 		LIST_INIT(&rule->arg.map.key);
 		proxy->conf.args.ctx = ARGC_HRS;
+		error = NULL;
 		if (!parse_logformat_string(args[cur_arg], proxy, &rule->arg.map.key, LOG_OPT_HTTP,
-		                            (proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR)) {
+		                            (proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR, &error)) {
+			Alert("parsing [%s:%d]: 'http-response %s': %s.\n",
+			      file, linenum, args[0], error);
+			free(error);
 			goto out_err;
 		}
 		free(proxy->conf.lfs_file);
@@ -9688,8 +9732,12 @@
 
 		LIST_INIT(&rule->arg.map.key);
 		proxy->conf.args.ctx = ARGC_HRS;
+		error = NULL;
 		if (!parse_logformat_string(args[cur_arg], proxy, &rule->arg.map.key, LOG_OPT_HTTP,
-		                            (proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR)) {
+		                            (proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR, &error)) {
+			Alert("parsing [%s:%d]: 'http-response %s' %s.\n",
+			      file, linenum, args[0], error);
+			free(error);
 			goto out_err;
 		}
 		free(proxy->conf.lfs_file);
@@ -9720,14 +9768,22 @@
 		proxy->conf.args.ctx = ARGC_HRS;
 
 		/* key pattern */
+		error = NULL;
 		if (!parse_logformat_string(args[cur_arg], proxy, &rule->arg.map.key, LOG_OPT_HTTP,
-		                            (proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR)) {
+		                            (proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR, &error)) {
+			Alert("parsing [%s:%d]: 'http-response %s' name: %s.\n",
+			      file, linenum, args[0], error);
+			free(error);
 			goto out_err;
 		}
 
 		/* value pattern */
+		error = NULL;
 		if (!parse_logformat_string(args[cur_arg + 1], proxy, &rule->arg.map.value, LOG_OPT_HTTP,
-		                            (proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR)) {
+		                            (proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR, &error)) {
+			Alert("parsing [%s:%d]: 'http-response %s' value: %s.\n",
+			      file, linenum, args[0], error);
+			free(error);
 			goto out_err;
 		}
 
@@ -9975,7 +10031,8 @@
 		if (!(type == REDIRECT_TYPE_PREFIX && destination[0] == '/' && destination[1] == '\0')) {
 			if (!parse_logformat_string(destination, curproxy, &rule->rdr_fmt, LOG_OPT_HTTP,
 			                            dir ? (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRS_HDR : SMP_VAL_BE_HRS_HDR
-			                                : (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR)) {
+			                                : (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
+			                            errmsg)) {
 				return  NULL;
 			}
 			free(curproxy->conf.lfs_file);
@@ -12471,7 +12528,7 @@
 	LIST_INIT(&rule->arg.http.logfmt);
 	proxy->conf.args.ctx = ARGC_HRQ;
 	if (!parse_logformat_string(args[cur_arg], proxy, &rule->arg.http.logfmt, LOG_OPT_HTTP,
-	                            (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR)) {
+	                            (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, err)) {
 		return ACT_RET_PRS_ERR;
 	}