{"record":{"id":"0fb205e37509563d","repo":"mongodb/laravel-mongodb","slug":"there-is-no-active-session","errorCode":null,"errorMessage":"There is no active session.","messagePattern":"There is no active session\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/Concerns/ManagesTransactions.php","lineNumber":48,"sourceCode":"    {\n        return $this->session;\n    }\n\n    private function getSessionOrCreate(): Session\n    {\n        if ($this->session === null) {\n            $this->session = $this->getClient()->startSession();\n        }\n\n        return $this->session;\n    }\n\n    private function getSessionOrThrow(): Session\n    {\n        $session = $this->getSession();\n\n        if ($session === null) {\n            throw new RuntimeException('There is no active session.');\n        }\n\n        return $session;\n    }\n\n    /**\n     * Starts a transaction on the active session. An active session will be created if none exists.\n     */\n    public function beginTransaction(array $options = []): void\n    {\n        $this->runCallbacksBeforeTransaction();\n\n        $this->getSessionOrCreate()->startTransaction($options);\n\n        $this->handleInitialTransactionState();\n    }\n\n    private function handleInitialTransactionState(): void","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/mongodb/laravel-mongodb/blob/0634653039468ceb0268a69192bdac64469ed043/src/Concerns/ManagesTransactions.php#L30-L66","documentation":"ManagesTransactions::commit() and rollBack() require an active MongoDB client session (started via beginTransaction). getSessionOrThrow() throws RuntimeException when no session exists, meaning these methods were called without a prior transaction start or after the session ended.","triggerScenarios":"Calling commit() or rollBack() on a MongoDB connection without calling beginTransaction() first, or after the transaction already committed/rolled back and the session was cleared.","commonSituations":"Code ported from SQL-based Laravel where implicit transactions exist; calling commit in a finally block after an exception already rolled the transaction back; unbalanced begin/commit calls across code paths.","solutions":["Call beginTransaction() before commit()/rollBack()","Check $connection->getSession() !== null before committing or rolling back","Balance transaction calls so every commit/rollBack follows an active beginTransaction","Use a transaction callback (e.g. transaction() helper) instead of manual begin/commit to guarantee pairing"],"exampleFix":"// before\n$connection->rollBack(); // no transaction started\n// after\n$connection->beginTransaction();\ntry {\n    // work\n    $connection->commit();\n} catch (Throwable $e) {\n    $connection->rollBack();\n    throw $e;\n}","handlingStrategy":"type-guard","validationCode":"if ($connection->getSession() === null) {\n    $connection->beginTransaction();\n}","typeGuard":"function hasActiveSession($connection): bool {\n    return $connection->getSession() !== null;\n}","tryCatchPattern":"try {\n    $connection->commit();\n} catch (RuntimeException $e) {\n    if (str_contains($e->getMessage(), 'no active session')) {\n        // transaction was never started or already closed — handle idempotently\n    } else {\n        throw $e;\n    }\n}","preventionTips":["Prefer the transaction() callback helper over manual begin/commit","Never call commit/rollBack in finally blocks without checking session state","Keep begin/commit pairing inside a single method to avoid leaked transactions"],"tags":["transactions","state"],"backgroundTag":"invalid-state-transition","analyzedSha":"0634653039468ceb0268a69192bdac64469ed043","analyzedAt":"2026-09-15T02:56:37.067Z","contentChangedAt":"2026-09-15T02:56:37.067Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}