firefly-iii/firefly-iii · error · FireflyException
300002
300002
Error message
300002: Journal #%d has multiple source transactions.
What it means
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.
Source
Thrown at app/Console/Commands/Correction/CorrectsTransactionTypes.php:152
$account = $transaction->account;
if (null === $account) {
throw new FireflyException(sprintf('300006: Journal #%d, transaction #%d has no destination account.', $journal->id, $transaction->id));
}
return $account;
}
/**
* @throws FireflyException
*/
private function getSourceAccount(TransactionJournal $journal): Account
{
$collection = $journal->transactions->filter(static fn (Transaction $transaction): bool => $transaction->amount < 0);
if (0 === $collection->count()) {
throw new FireflyException(sprintf('300001: Journal #%d has no source transaction.', $journal->id));
}
if (1 !== $collection->count()) {
throw new FireflyException(sprintf('300002: Journal #%d has multiple source transactions.', $journal->id));
}
/** @var Transaction $transaction */
$transaction = $collection->first();
/** @var null|Account $account */
$account = $transaction->account;
if (null === $account) {
throw new FireflyException(sprintf('300003: Journal #%d, transaction #%d has no source account.', $journal->id, $transaction->id));
}
return $account;
}
}
View on GitHub (pinned to fd8791d08d)
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.
Example fix
-- find duplicate source legs SELECT transaction_journal_id, COUNT(*) c FROM transactions WHERE amount < 0 GROUP BY transaction_journal_id HAVING c > 1; -- after backup, remove extras by id DELETE FROM transactions WHERE id = <duplicate_id>;
Defensive patterns
Strategy: try-catch
Validate before calling
-- pre-flight: duplicate source legs SELECT transaction_journal_id FROM transactions WHERE amount < 0 GROUP BY transaction_journal_id HAVING COUNT(*) > 1;
Try / catch
try {
$this->artisan('correction:transaction-types');
} catch (FireflyException $e) {
if (preg_match('/300002: Journal #(\d+)/', $e->getMessage(), $m)) {
// keep one negative row for journal (int)$m[1], delete extras, re-run
}
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
AI-assisted analysis of firefly-iii/firefly-iii@fd8791d08d (2026-08-17).
Data as JSON: /api/errors/8d2d048e035cb185.
Report an issue: GitHub.