diff --git a/NEWS b/NEWS
index caad04f9d0895..aa8b016adcbe8 100644
--- a/NEWS
+++ b/NEWS
@@ -32,6 +32,10 @@ PHP                                                                        NEWS
     (David Carlier)
   . Fix UConverter::transcode with substitutes as references. (David Carlier)
 
+- libxml:
+  . Fixed custom external entity loader returning an invalid resource leading
+    to a confusing TypeError message. (Girgias)
+
 - Mbstring:
   . Fixed bug GH-17989 (mb_output_handler crash with unset
     http_output_conv_mimetypes). (nielsdos)
diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c
index 18ca51e36a052..5c903d2c9a228 100644
--- a/ext/libxml/libxml.c
+++ b/ext/libxml/libxml.c
@@ -793,13 +793,18 @@ static xmlParserInputPtr _php_libxml_external_entity_loader(const char *URL,
 is_string:
 			resource = Z_STRVAL(retval);
 		} else if (Z_TYPE(retval) == IS_RESOURCE) {
-			php_stream *stream;
-			php_stream_from_zval_no_verify(stream, &retval);
-			if (stream == NULL) {
-				php_libxml_ctx_error(context,
-						"The user entity loader callback '%s' has returned a "
-						"resource, but it is not a stream",
-						ZSTR_VAL(LIBXML(entity_loader_callback).function_handler->common.function_name));
+			php_stream *stream = (php_stream*)zend_fetch_resource2_ex(&retval, NULL, php_file_le_stream(), php_file_le_pstream());
+			if (UNEXPECTED(stream == NULL)) {
+				zval callable;
+				zend_get_callable_zval_from_fcc(&LIBXML(entity_loader_callback), &callable);
+				zend_string *callable_name = zend_get_callable_name(&callable);
+				zend_string *func_name = get_active_function_or_method_name();
+				zend_type_error(
+					"%s(): The user entity loader callback \"%s\" has returned a resource, but it is not a stream",
+					ZSTR_VAL(func_name), ZSTR_VAL(callable_name));
+				zend_string_release(func_name);
+				zend_string_release(callable_name);
+				zval_ptr_dtor(&callable);
 			} else {
 				/* TODO: allow storing the encoding in the stream context? */
 				xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
diff --git a/ext/libxml/tests/libxml_get_external_entity_loader_error_callback_name.phpt b/ext/libxml/tests/libxml_get_external_entity_loader_error_callback_name.phpt
index 1bdbbfb5b817e..2122785ef5b9b 100644
--- a/ext/libxml/tests/libxml_get_external_entity_loader_error_callback_name.phpt
+++ b/ext/libxml/tests/libxml_get_external_entity_loader_error_callback_name.phpt
@@ -40,4 +40,4 @@ $file = __DIR__ . '/db.dba';
 unlink($file);
 ?>
 --EXPECT--
-string(73) "DOMDocument::validate(): supplied resource is not a valid stream resource"
+string(122) "DOMDocument::validate(): The user entity loader callback "Handler::handle" has returned a resource, but it is not a stream"