{"record":{"id":"8d2d048e035cb185","repo":"firefly-iii/firefly-iii","slug":"300002","errorCode":"300002","errorMessage":"300002: Journal #%d has multiple source transactions.","messagePattern":"300002: Journal #(.+?) has multiple source transactions\\.","errorType":"console","errorClass":"FireflyException","httpStatus":null,"severity":"error","filePath":"app/Console/Commands/Correction/CorrectsTransactionTypes.php","lineNumber":152,"sourceCode":"        $account     = $transaction->account;\n        if (null === $account) {\n            throw new FireflyException(sprintf('300006: Journal #%d, transaction #%d has no destination account.', $journal->id, $transaction->id));\n        }\n\n        return $account;\n    }\n\n    /**\n     * @throws FireflyException\n     */\n    private function getSourceAccount(TransactionJournal $journal): Account\n    {\n        $collection  = $journal->transactions->filter(static fn (Transaction $transaction): bool => $transaction->amount < 0);\n        if (0 === $collection->count()) {\n            throw new FireflyException(sprintf('300001: Journal #%d has no source transaction.', $journal->id));\n        }\n        if (1 !== $collection->count()) {\n            throw new FireflyException(sprintf('300002: Journal #%d has multiple source transactions.', $journal->id));\n        }\n\n        /** @var Transaction $transaction */\n        $transaction = $collection->first();\n\n        /** @var null|Account $account */\n        $account     = $transaction->account;\n        if (null === $account) {\n            throw new FireflyException(sprintf('300003: Journal #%d, transaction #%d has no source account.', $journal->id, $transaction->id));\n        }\n\n        return $account;\n    }\n}\n","sourceCodeStart":134,"sourceCodeEnd":167,"githubUrl":"https://github.com/firefly-iii/firefly-iii/blob/fd8791d08d4d9e6467519a78048cd038e26b8878/app/Console/Commands/Correction/CorrectsTransactionTypes.php#L134-L167","documentation":"Thrown by correction:transaction-types when a journal has two or more transaction rows with amount < 0. Code 300002: multiple source legs make it ambiguous which account is the source, so type correction aborts. Healthy journals have exactly one negative and one positive row.","triggerScenarios":"Running firefly-iii:correct-database or correction:transaction-types on a journal with duplicated negative-amount transaction rows — double imports, repeated migration runs, or copied rows in SQL.","commonSituations":"Re-running an importer that lacks idempotency. Interrupted upgrade runs that inserted legs twice. Manual database surgery where rows were copied to 'back them up' inside the same table.","solutions":["List the duplicates: SELECT id, amount, account_id FROM transactions WHERE transaction_journal_id = <id> AND amount < 0.","Back up, then keep one negative-amount row (valid account_id) and delete the others.","Confirm the journal balances (sum of amounts = 0) with correction:uneven-amounts.","Re-run the correction command until it passes cleanly."],"exampleFix":"-- find duplicate source legs\nSELECT transaction_journal_id, COUNT(*) c FROM transactions WHERE amount < 0 GROUP BY transaction_journal_id HAVING c > 1;\n\n-- after backup, remove extras by id\nDELETE FROM transactions WHERE id = <duplicate_id>;","handlingStrategy":"try-catch","validationCode":"-- pre-flight: duplicate source legs\nSELECT transaction_journal_id FROM transactions WHERE amount < 0\nGROUP BY transaction_journal_id HAVING COUNT(*) > 1;","typeGuard":null,"tryCatchPattern":"try {\n    $this->artisan('correction:transaction-types');\n} catch (FireflyException $e) {\n    if (preg_match('/300002: Journal #(\\d+)/', $e->getMessage(), $m)) {\n        // keep one negative row for journal (int)$m[1], delete extras, re-run\n    }\n}","preventionTips":["Guard imports with existence checks per journal before inserting legs.","Avoid copy-pasting rows inside the transactions table for 'backups'.","After any manual fix, verify each journal has exactly 2 rows summing to zero."],"tags":["console","correction-command","data-integrity","duplicate-data","database","error-code"],"backgroundTag":"duplicate-database-rows","analyzedSha":"fd8791d08d4d9e6467519a78048cd038e26b8878","analyzedAt":"2026-08-17T02:14:53.848Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}