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

  1. List the duplicates: SELECT id, amount, account_id FROM transactions WHERE transaction_journal_id = <id> AND amount < 0.
  2. Back up, then keep one negative-amount row (valid account_id) and delete the others.
  3. Confirm the journal balances (sum of amounts = 0) with correction:uneven-amounts.
  4. 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

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.