diff --git a/typo3/sysext/core/Classes/Authentication/BackendUserAuthentication.php b/typo3/sysext/core/Classes/Authentication/BackendUserAuthentication.php
index 2616b3e6d12bb5017125ac394714aa0aa7d251d6..6d481cdd0585225cc27bfe647e3cdebf07c40777 100644
--- a/typo3/sysext/core/Classes/Authentication/BackendUserAuthentication.php
+++ b/typo3/sysext/core/Classes/Authentication/BackendUserAuthentication.php
@@ -48,7 +48,6 @@ use TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser;
 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\StringUtility;
-use TYPO3\CMS\Core\Versioning\VersionState;
 use TYPO3\CMS\Install\Service\SessionService;
 
 /**
@@ -858,88 +857,6 @@ class BackendUserAuthentication extends AbstractUserAuthentication
             && !($this->getTSConfig()['options.']['mayNotCreateEditBookmarks'] ?? false);
     }
 
-    /**
-     * Checking if editing of an existing record is allowed in current workspace if that is offline.
-     * Rules for editing in offline mode:
-     * - record supports versioning and is an offline version from workspace and has the current stage
-     * - or record (any) is in a branch where there is a page which is a version from the workspace
-     *   and where the stage is not preventing records
-     *
-     * @param string $table Table of record
-     * @param array|int $recData Integer (record uid) or array where fields are at least: pid, t3ver_wsid, t3ver_oid, t3ver_stage (if versioningWS is set)
-     * @return string String error code, telling the failure state. FALSE=All ok
-     * @internal should only be used from within TYPO3 Core
-     */
-    public function workspaceCannotEditRecord($table, $recData)
-    {
-        // Only test if the user is in a workspace
-        if ($this->workspace === 0) {
-            return false;
-        }
-        $tableSupportsVersioning = BackendUtility::isTableWorkspaceEnabled($table);
-        if (!is_array($recData)) {
-            $recData = BackendUtility::getRecord(
-                $table,
-                $recData,
-                'pid' . ($tableSupportsVersioning ? ',t3ver_oid,t3ver_wsid,t3ver_state,t3ver_stage' : '')
-            );
-        }
-        if (is_array($recData)) {
-            // We are testing a "version" (identified by having a t3ver_oid): it can be edited provided
-            // that workspace matches and versioning is enabled for the table.
-            $versionState = new VersionState($recData['t3ver_state'] ?? 0);
-            if ($tableSupportsVersioning
-                && (
-                    $versionState->equals(VersionState::NEW_PLACEHOLDER) || (int)(($recData['t3ver_oid'] ?? 0) > 0)
-                )
-            ) {
-                if ((int)$recData['t3ver_wsid'] !== $this->workspace) {
-                    // So does workspace match?
-                    return 'Workspace ID of record didn\'t match current workspace';
-                }
-                // So is the user allowed to "use" the edit stage within the workspace?
-                return $this->workspaceCheckStageForCurrent(0)
-                        ? false
-                        : 'User\'s access level did not allow for editing';
-            }
-            // Check if we are testing a "live" record
-            if ($this->workspaceAllowsLiveEditingInTable($table)) {
-                // Live records are OK in the current workspace
-                return false;
-            }
-            // If not offline, output error
-            return 'Online record was not in a workspace!';
-        }
-        return 'No record';
-    }
-
-    /**
-     * Evaluates if a user is allowed to edit the offline version
-     *
-     * @param string $table Table of record
-     * @param array|int $recData Integer (record uid) or array where fields are at least: pid, t3ver_wsid, t3ver_stage (if versioningWS is set)
-     * @return string String error code, telling the failure state. FALSE=All ok
-     * @see workspaceCannotEditRecord()
-     * @internal this method will be moved to EXT:workspaces
-     */
-    public function workspaceCannotEditOfflineVersion($table, $recData)
-    {
-        if (!BackendUtility::isTableWorkspaceEnabled($table)) {
-            return 'Table does not support versioning.';
-        }
-        if (!is_array($recData)) {
-            $recData = BackendUtility::getRecord($table, $recData, 'uid,pid,t3ver_oid,t3ver_wsid,t3ver_state,t3ver_stage');
-        }
-        if (is_array($recData)) {
-            $versionState = new VersionState($recData['t3ver_state']);
-            if ($versionState->equals(VersionState::NEW_PLACEHOLDER) || (int)$recData['t3ver_oid'] > 0) {
-                return $this->workspaceCannotEditRecord($table, $recData);
-            }
-            return 'Not an offline version';
-        }
-        return 'No record';
-    }
-
     /**
      * Checks if a record is allowed to be edited in the current workspace.
      * This is not bound to an actual record, but to the mere fact if the user is in a workspace
@@ -988,38 +905,6 @@ class BackendUserAuthentication extends AbstractUserAuthentication
         return true;
     }
 
-    /**
-     * Evaluates if auto creation of a version of a record is allowed.
-     * Auto-creation of version: In offline workspace, test if versioning is
-     * enabled and look for workspace version of input record.
-     * If there is no versionized record found we will create one and save to that.
-     *
-     * @param string $table Table of the record
-     * @param int $id UID of record
-     * @param int $recpid PID of record
-     * @return bool TRUE if ok.
-     * @internal should only be used from within TYPO3 Core
-     */
-    public function workspaceAllowAutoCreation($table, $id, $recpid)
-    {
-        // No version can be created in live workspace
-        if ($this->workspace === 0) {
-            return false;
-        }
-        // No versioning support for this table, so no version can be created
-        if (!BackendUtility::isTableWorkspaceEnabled($table)) {
-            return false;
-        }
-        if ($recpid < 0) {
-            return false;
-        }
-        // There must be no existing version of this record in workspace
-        if (BackendUtility::getWorkspaceVersionOfRecord($this->workspace, $table, $id, 'uid')) {
-            return false;
-        }
-        return true;
-    }
-
     /**
      * Checks if an element stage allows access for the user in the current workspace
      * In live workspace (= 0) access is always granted for any stage.
diff --git a/typo3/sysext/core/Classes/DataHandling/DataHandler.php b/typo3/sysext/core/Classes/DataHandling/DataHandler.php
index 02c9dc74238b9228d4e78656008ebdf4d3699cf9..2c7b7175555adf710f2df84af48f645ade56af94 100644
--- a/typo3/sysext/core/Classes/DataHandling/DataHandler.php
+++ b/typo3/sysext/core/Classes/DataHandling/DataHandler.php
@@ -999,7 +999,7 @@ class DataHandler implements LoggerAwareInterface
                             // Use the new id of the copied/versionized record:
                             $id = $this->autoVersionIdMap[$table][$id];
                             $recordAccess = true;
-                        } elseif (!$this->bypassWorkspaceRestrictions && ($errorCode = $this->BE_USER->workspaceCannotEditRecord($table, $tempdata))) {
+                        } elseif (!$this->bypassWorkspaceRestrictions && $tempdata && ($errorCode = $this->workspaceCannotEditRecord($table, $tempdata))) {
                             $recordAccess = false;
                             // Versioning is required and it must be offline version!
                             // Check if there already is a workspace version
@@ -1007,7 +1007,7 @@ class DataHandler implements LoggerAwareInterface
                             if ($workspaceVersion) {
                                 $id = $workspaceVersion['uid'];
                                 $recordAccess = true;
-                            } elseif ($this->BE_USER->workspaceAllowAutoCreation($table, $id, $theRealPid)) {
+                            } elseif ($this->workspaceAllowAutoCreation($table, $id, $theRealPid)) {
                                 // new version of a record created in a workspace - so always refresh pagetree to indicate there is a change in the workspace
                                 $this->pagetreeNeedsRefresh = true;
 
@@ -5577,7 +5577,7 @@ class DataHandler implements LoggerAwareInterface
             $this->log($table, $versionRecord['uid'], SystemLogDatabaseAction::DISCARD, 0, SystemLogErrorClassification::USER_ERROR, 'Attempt to discard workspace record ' . $table . ':' . $versionRecord['uid'] . ' failed: Different workspace');
             return;
         }
-        if ($errorCode = $this->BE_USER->workspaceCannotEditOfflineVersion($table, $versionRecord['uid'])) {
+        if ($errorCode = $this->workspaceCannotEditOfflineVersion($table, $versionRecord)) {
             $this->log($table, $versionRecord['uid'], SystemLogDatabaseAction::DISCARD, 0, SystemLogErrorClassification::USER_ERROR, 'Attempt to discard workspace record ' . $table . ':' . $versionRecord['uid'] . ' failed: ' . $errorCode);
             return;
         }
@@ -9032,6 +9032,114 @@ class DataHandler implements LoggerAwareInterface
         return $records;
     }
 
+    /**
+     * Evaluates if auto creation of a version of a record is allowed.
+     * Auto-creation of version: In offline workspace, test if versioning is
+     * enabled and look for workspace version of input record.
+     * If there is no versionized record found we will create one and save to that.
+     *
+     * @param string $table Table of the record
+     * @param int $id UID of record
+     * @param int|null $recpid PID of record
+     * @return bool TRUE if ok.
+     * @internal should only be used from within TYPO3 Core
+     */
+    protected function workspaceAllowAutoCreation(string $table, $id, $recpid): bool
+    {
+        // No version can be created in live workspace
+        if ($this->BE_USER->workspace === 0) {
+            return false;
+        }
+        // No versioning support for this table, so no version can be created
+        if (!BackendUtility::isTableWorkspaceEnabled($table)) {
+            return false;
+        }
+        if ($recpid < 0) {
+            return false;
+        }
+        // There must be no existing version of this record in workspace
+        if (BackendUtility::getWorkspaceVersionOfRecord($this->BE_USER->workspace, $table, $id, 'uid')) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Evaluates if a user is allowed to edit the offline version
+     *
+     * @param string $table Table of record
+     * @param array $record array where fields are at least: pid, t3ver_wsid, t3ver_stage (if versioningWS is set)
+     * @return string String error code, telling the failure state. FALSE=All ok
+     * @see workspaceCannotEditRecord()
+     * @internal this method will be moved to EXT:workspaces
+     */
+    public function workspaceCannotEditOfflineVersion(string $table, array $record)
+    {
+        if (!BackendUtility::isTableWorkspaceEnabled($table)) {
+            return 'Table does not support versioning.';
+        }
+        $versionState = new VersionState($record['t3ver_state']);
+        if ($versionState->equals(VersionState::NEW_PLACEHOLDER) || (int)$record['t3ver_oid'] > 0) {
+            return $this->workspaceCannotEditRecord($table, $record);
+        }
+        return 'Not an offline version';
+    }
+
+    /**
+     * Checking if editing of an existing record is allowed in current workspace if that is offline.
+     * Rules for editing in offline mode:
+     * - record supports versioning and is an offline version from workspace and has the current stage
+     * - or record (any) is in a branch where there is a page which is a version from the workspace
+     *   and where the stage is not preventing records
+     *
+     * @param string $table Table of record
+     * @param array|int $recData Integer (record uid) or array where fields are at least: pid, t3ver_wsid, t3ver_oid, t3ver_stage (if versioningWS is set)
+     * @return string String error code, telling the failure state. FALSE=All ok
+     * @internal should only be used from within TYPO3 Core
+     */
+    public function workspaceCannotEditRecord($table, $recData)
+    {
+        // Only test if the user is in a workspace
+        if ($this->BE_USER->workspace === 0) {
+            return false;
+        }
+        $tableSupportsVersioning = BackendUtility::isTableWorkspaceEnabled($table);
+        if (!is_array($recData)) {
+            $recData = BackendUtility::getRecord(
+                $table,
+                $recData,
+                'pid' . ($tableSupportsVersioning ? ',t3ver_oid,t3ver_wsid,t3ver_state,t3ver_stage' : '')
+            );
+        }
+        if (is_array($recData)) {
+            // We are testing a "version" (identified by having a t3ver_oid): it can be edited provided
+            // that workspace matches and versioning is enabled for the table.
+            $versionState = new VersionState($recData['t3ver_state'] ?? 0);
+            if ($tableSupportsVersioning
+                && (
+                    $versionState->equals(VersionState::NEW_PLACEHOLDER) || (int)(($recData['t3ver_oid'] ?? 0) > 0)
+                )
+            ) {
+                if ((int)$recData['t3ver_wsid'] !== $this->BE_USER->workspace) {
+                    // So does workspace match?
+                    return 'Workspace ID of record didn\'t match current workspace';
+                }
+                // So is the user allowed to "use" the edit stage within the workspace?
+                return $this->BE_USER->workspaceCheckStageForCurrent(0)
+                    ? false
+                    : 'User\'s access level did not allow for editing';
+            }
+            // Check if we are testing a "live" record
+            if ($this->BE_USER->workspaceAllowsLiveEditingInTable($table)) {
+                // Live records are OK in the current workspace
+                return false;
+            }
+            // If not offline, output error
+            return 'Online record was not in a workspace!';
+        }
+        return 'No record';
+    }
+
     /**
      * Gets the outer most instance of \TYPO3\CMS\Core\DataHandling\DataHandler
      * Since \TYPO3\CMS\Core\DataHandling\DataHandler can create nested objects of itself,
diff --git a/typo3/sysext/workspaces/Classes/Hook/DataHandlerHook.php b/typo3/sysext/workspaces/Classes/Hook/DataHandlerHook.php
index 901487510e017753f4057022f5b8292d5a9f071d..7086f25e836ce9bca1beec675da6e67588c6ec1e 100644
--- a/typo3/sysext/workspaces/Classes/Hook/DataHandlerHook.php
+++ b/typo3/sysext/workspaces/Classes/Hook/DataHandlerHook.php
@@ -361,7 +361,7 @@ class DataHandlerHook
         $canMoveRecord = $recIsNewVersion || $tableSupportsVersioning;
         // Workspace source check:
         if (!$recIsNewVersion) {
-            $errorCode = $dataHandler->BE_USER->workspaceCannotEditRecord($table, $versionedRecord['uid'] ?: $uid);
+            $errorCode = $dataHandler->workspaceCannotEditRecord($table, $versionedRecord['uid'] ?: $uid);
             if ($errorCode) {
                 $workspaceAccessBlocked['src1'] = 'Record could not be edited in workspace: ' . $errorCode . ' ';
             } elseif (!$canMoveRecord && !$recordMustNotBeVersionized) {
@@ -479,10 +479,12 @@ class DataHandlerHook
      */
     protected function version_setStage($table, $id, $stageId, string $comment, DataHandler $dataHandler, array $notificationAlternativeRecipients = [])
     {
-        if ($errorCode = $dataHandler->BE_USER->workspaceCannotEditOfflineVersion($table, $id)) {
+        $record = BackendUtility::getRecord($table, $id);
+        if (!is_array($record)) {
+            $dataHandler->log($table, $id, DatabaseAction::VERSIONIZE, 0, SystemLogErrorClassification::USER_ERROR, 'Attempt to set stage for record failed: No Record');
+        } elseif ($errorCode = $dataHandler->workspaceCannotEditOfflineVersion($table, $record)) {
             $dataHandler->log($table, $id, DatabaseAction::VERSIONIZE, 0, SystemLogErrorClassification::USER_ERROR, 'Attempt to set stage for record failed: ' . $errorCode);
         } elseif ($dataHandler->checkRecordUpdateAccess($table, $id)) {
-            $record = BackendUtility::getRecord($table, $id);
             $workspaceInfo = $dataHandler->BE_USER->checkWorkspace($record['t3ver_wsid']);
             // check if the user is allowed to the current stage, so it's also allowed to send to next stage
             if ($dataHandler->BE_USER->workspaceCheckStageForCurrent($record['t3ver_stage'])) {