diff --git a/project/common.mk b/project/common.mk
index 5f11b1b..9eb2105 100644
--- a/project/common.mk
+++ b/project/common.mk
@@ -2,6 +2,7 @@ COMMON_SRCS = \
 	src/driver/sfrt_amain.c \
 	src/driver/sfrt_driver_ctx.c \
 	src/driver/sfrt_unit_ctx.c \
+	src/internal/sofort_errinfo_impl.c \
 	src/logic/sfrt_map_input.c \
 	src/output/sfrt_output_address.c \
 	src/output/sfrt_output_dummy.c \
diff --git a/project/headers.mk b/project/headers.mk
index 1fb0cd2..60a7eb3 100644
--- a/project/headers.mk
+++ b/project/headers.mk
@@ -5,5 +5,6 @@ API_HEADERS = \
 INTERNAL_HEADERS = \
 	$(PROJECT_DIR)/src/internal/argv/argv.h \
 	$(PROJECT_DIR)/src/internal/$(PACKAGE)_driver_impl.h \
+	$(PROJECT_DIR)/src/internal/$(PACKAGE)_errinfo_impl.h \
 
 ALL_HEADERS = $(API_HEADERS) $(INTERNAL_HEADERS)
diff --git a/src/internal/sofort_errinfo_impl.c b/src/internal/sofort_errinfo_impl.c
new file mode 100644
index 0000000..31b008a
--- /dev/null
+++ b/src/internal/sofort_errinfo_impl.c
@@ -0,0 +1,39 @@
+#include <sofort/sofort.h>
+#include "sofort_driver_impl.h"
+#include "sofort_errinfo_impl.h"
+
+int sfrt_record_error(
+	const struct sfrt_driver_ctx *	dctx,
+	int				esyscode,
+	int				elibcode,
+	const char *			efunction,
+	int				eline,
+	unsigned			eflags,
+	void *				eany)
+{
+	struct sfrt_driver_ctx_impl *	ictx;
+	struct sfrt_error_info *	erri;
+
+	ictx = sfrt_get_driver_ictx(dctx);
+
+	if (ictx->errinfp == ictx->erricap)
+		return -1;
+
+	*ictx->errinfp = &ictx->erribuf[ictx->errinfp - ictx->erriptr];
+	erri = *ictx->errinfp;
+
+	erri->euctx     = ictx->euctx;
+	erri->eunit     = ictx->eunit;
+
+	erri->edctx     = dctx;
+	erri->esyscode  = esyscode;
+	erri->elibcode  = elibcode;
+	erri->efunction = efunction;
+	erri->eline     = eline;
+	erri->eflags    = eflags;
+	erri->eany      = eany;
+
+	ictx->errinfp++;
+
+	return -1;
+}
diff --git a/src/internal/sofort_errinfo_impl.h b/src/internal/sofort_errinfo_impl.h
new file mode 100644
index 0000000..8d42fc3
--- /dev/null
+++ b/src/internal/sofort_errinfo_impl.h
@@ -0,0 +1,74 @@
+#include <errno.h>
+#include <sofort/sofort.h>
+
+int sfrt_record_error(
+	const struct sfrt_driver_ctx *,
+	int		esyscode,
+	int		elibcode,
+	const char *	efunction,
+	int		eline,
+	unsigned	eflags,
+	void *		ectx);
+
+#define SFRT_SYSTEM_ERROR(dctx)           \
+	sfrt_record_error(                \
+		dctx,                     \
+		errno,                    \
+		0,                        \
+		__func__,                 \
+		__LINE__,                 \
+		SFRT_ERROR_TOP_LEVEL,     \
+		0)
+
+#define SFRT_BUFFER_ERROR(dctx)           \
+	sfrt_record_error(                \
+		dctx,                     \
+		ENOBUFS,                  \
+		0,                        \
+		__func__,                 \
+		__LINE__,                 \
+		SFRT_ERROR_TOP_LEVEL,     \
+		0)
+
+#define SFRT_SPAWN_ERROR(dctx)            \
+	sfrt_record_error(                \
+		dctx,                     \
+		errno,                    \
+		0,                        \
+		__func__,                 \
+		__LINE__,                 \
+		SFRT_ERROR_TOP_LEVEL      \
+		| (errno ? 0              \
+		   : SFRT_ERROR_CHILD),   \
+		0)
+
+#define SFRT_FILE_ERROR(dctx)             \
+	sfrt_record_error(                \
+		dctx,                     \
+		EIO,                      \
+		0,                        \
+		__func__,                 \
+		__LINE__,                 \
+		SFRT_ERROR_TOP_LEVEL,     \
+		0)
+
+#define SFRT_CUSTOM_ERROR(dctx,elibcode)  \
+	sfrt_record_error(                \
+		dctx,                     \
+		0,                        \
+		elibcode,                 \
+		__func__,                 \
+		__LINE__,                 \
+		SFRT_ERROR_TOP_LEVEL      \
+		| SFRT_ERROR_CUSTOM,      \
+		0)
+
+#define SFRT_NESTED_ERROR(dctx)           \
+	sfrt_record_error(                \
+		dctx,                     \
+		0,                        \
+		0,                        \
+		__func__,                 \
+		__LINE__,                 \
+		SFRT_ERROR_NESTED,        \
+		0)