Troubleshooting
The failures operators actually report on the Forex Investment addon — investments that never settle, plans nobody can invest in, deposits that will not go through, empty signal lists — and what each one really is.
Almost every report against this addon is one of four things: the cron is not running, a plan is misconfigured, an account's currency does not match the plan, or the wallet type cannot be funded. Check those before anything else.
Investments never settle
Open /admin/system/cron and find processForexInvestments under the forex
category. It is the only thing in the product that settles an investment.
If it has never run, the cron process is not alive — that is a platform
problem, not a forex one. If it has run but shows a lastRunError, read the
error: it is almost always a database issue.
The principal has already left the customer's forex account, so nothing returns it until this job runs. Fix the cron and the backlog settles on the next tick.
Three causes, in order of likelihood.
Its plan or duration was deleted. The settlement job resolves both through
a soft-delete-aware include, so a deleted plan makes the investment
unresolvable. It is logged and left ACTIVE deliberately — the alternative is
cancelling it, and that is not a decision a cron should make. The cron log says
has no associated plan; skipped (left ACTIVE for manual review).
Restore the plan row and it settles on the next tick.
The customer has no LIVE forex account. Settlement pays into the account
the principal came from. If it was deleted, there is nowhere to pay and the
investment is left ACTIVE. Recreate the account, or cancel the investment —
which refunds, and will also fail without an account to refund to.
Three attempts failed. After three retries the job cancels the investment
and refunds the principal in the same transaction, and the customer is
notified. If a safe refund was impossible the investment stays ACTIVE and the
log carries an ALERT.
They were. Payouts go into the forex account, not the wallet. The customer
takes them out through /forex/dashboard → Withdraw, which lands in your
approval queue.
This changed deliberately: a matured investment used to pay straight into the spot wallet, bypassing the approval every other forex withdrawal requires.
Payouts are the wrong size
The plan's profit percentage is what settlement pays. If it is 0, every
win returns exactly the principal.
There is a second field, default profit, which older builds used for
settlement — a plan advertised at 15% whose default profit was left alone paid
nothing on every win. Settlement now uses the percentage the customer was
quoted. Check profitPercentage on the plan, not defaultProfit.
Settlement reads the plan at maturity, not a snapshot taken at purchase. If somebody raised the profit percentage while investments were open, every one of them settles at the new rate — including ones bought weeks ago.
To change terms going forward, create a new plan and disable the old one.
Check the plan's default result. It decides the direction of every
investment on the plan unless an admin sets result on the individual
investment first.
Investments settled before v6.1.2 store a loss as a positive number beside a
LOSS result. Every reporting surface in the addon corrects for this now; a
report you built yourself against forex_investment.profit will not. Apply
CASE WHEN result = 'LOSS' THEN -ABS(profit) ELSE profit END.
Nobody can invest
Plans are created with status off. The customer-facing plan list returns
only enabled plans. Enable it at /admin/forex/plan.
The plan has no durations attached, or not the one being tried. A duration must
be linked to a plan through forex_plan_duration before it can be used — a
plan's profit is a flat percentage that does not scale with time, so an
unscoped duration would let a customer take a 30-day plan's whole return in an
hour.
Edit the plan and set its duration options. A plan with none attached is completely dead: it lists, it opens, and every investment on it is refused.
The customer's forex account was bound to a different currency or wallet type by its first deposit, and the binding is permanent for as long as the account holds a balance. They cannot invest in this plan.
Either offer plans in the denomination they hold, or have them empty the
account — after which you can clear currency and walletType on the row and
let the next deposit rebind it. There is no admin button for this.
The plan's limits are transposed. Newly saved plans are refused with this
configuration, but plans created before that validation existed are still on
your install and are permanently unusable. Fix minAmount and maxAmount.
The principal comes from the forex account, not the wallet. A customer with money in their wallet but nothing deposited into forex sees this. They have to deposit first.
A hard limit of ten ACTIVE investments per customer, not configurable.
If this is happening on a current build, check that the balance being displayed is the forex account balance and not the wallet. An earlier build read the spot wallet on the invest form, so a customer who had deposited 5,000 into forex — exactly what the product asks — saw a balance of 0.
Deposits and withdrawals fail
The plan or the deposit is using a wallet type this addon cannot handle. Fee calculation supports FIAT and SPOT only.
The wallet type dropdown on the plan form offers ECO whenever the Ecosystem addon is installed, because it is the platform's generic list. A plan denominated in an ECO currency saves and publishes, and then every attempt to fund an account for it fails here. Move the plan to FIAT or SPOT.
The currency has no price on the local currency table and the refresh did not produce one. For a FIAT plan, check the fiat price feed; for SPOT, check your exchange currency rows.
A failure to read the exchange's network fee is no longer fatal — it costs the fixed fee and logs a warning. If both money doors are closed on an install with no working exchange credentials, you are on a build predating that fix.
Deposits require a client-supplied nonce of 8 to 128 characters so a retry after a timeout collapses onto the same operation rather than debiting the wallet twice. Any integration calling the deposit endpoint has to supply one, and reuse it across retries of the same intent.
The customer has made three or more withdrawals in the last 24 hours. More than five is refused outright. Neither figure is configurable.
The per-account caps. Defaults are 5,000 daily and 50,000 monthly, editable on
the account row at /admin/forex/account.
Note they are compared in the account's own currency units, not dollars — so on a BTC account the default is effectively no limit, and on a JPY account it is punishingly tight.
On builds before v6.1.2 the daily and monthly windows shared one anchor and the daily rollover overwrote it, so the monthly counter only reset after thirty consecutive days with no withdrawals at all. An active customer hit the monthly cap and was then locked out permanently — unable to withdraw and unable to have pending requests approved.
Update. The two windows are tracked independently and affected customers can withdraw again immediately.
Real money may only move against a LIVE account. If a customer is hitting this,
their LIVE account was never provisioned — usually because their verification
level does not carry create_forex_account.
Admin actions are refused
By design. The principal was collected when the investment was created, and changing the amount would change what it pays without changing what was taken. Cancel it — which refunds — and create a new one.
Deleting a plan or duration is refused while active investments reference it,
because forex_investment cascades from both at the database level. Settle or
cancel those investments first; cancelling refunds each principal.
A permanent delete (?force=true) is refused while any investment references
it, settled ones included — those rows are what your accounting is built from.
Deleting a pending withdrawal would leave the customer short with no refund and no record: the money has already left their forex account and is waiting on your decision. Reject it, which refunds properly, then delete.
Same shape. Deleting an active investment takes it out of the settlement cron's reach and the principal never comes back. Cancel first.
The customer has already spent the deposit you are trying to reverse. The account must still hold what the deposit credited. A human has to decide what happens next — this is not something the platform should guess at.
Cancelling an investment refunds the principal. Recovery re-arms it so it can settle, which would pay the principal again at maturity. Recovery therefore reclaims the refund first, and refuses when the forex account can no longer cover it.
One account per user per type, enforced. Every lookup in the addon reads this user's LIVE account with no ordering, so a duplicate makes it arbitrary which row is debited, credited or refunded. Edit the existing account.
Signals show nothing
Signals reach a customer through their forex account, and the only write
path is PUT /api/admin/forex/account/{id}/signal. There is no signal picker
on the admin account form, so if nobody has called that endpoint, every
customer's list is empty by construction.
See Signals.
Check its status. Signals are created inactive, and both customer-facing read paths filter on active signals only.
You are on a build predating the join fix. Both reads now join through the
account subscription with an inner join; with an outer join the subscription
filter sits in the ON clause and every active signal comes back regardless of
assignment.
The terminal will not connect
The /forex/trade/{id} screen embeds the public MetaTrader WebTerminal —
trade.mql5.com for an MT5 account, metatraderweb.app otherwise — using the
account's broker field as the server and accountId as the login.
If it does not connect, one of those two is wrong, or the account was auto-created empty because no pre-provisioned row existed to claim. The platform never talks to your broker, so there is nothing on this side to diagnose beyond the credentials on the account row. See Accounts.
The dashboard looks wrong
They did, and some of them because the old value was wrong. Money totals used to be summed across plan currencies and printed with a dollar sign; they are now grouped per currency with the largest pool headlined. On a single-currency install nothing changes but the label. On a mixed one the headline is smaller, because it is one pool rather than all of them added together.
Three month-over-month growth chips were also removed. They compared the current month to date against the whole previous month, so on the 2nd of any month all three read about −95% and then recovered over four weeks, on every install, regardless of how the desk was performing.
Look at the live indicator. It reports live, updating or stale, and it goes stale the moment a refresh fails. The page also refreshes only while the tab is visible — a background tab is deliberately idle.
On builds before v6.1.2 both pending counters were hard-coded to zero while
displaying as clickable tiles linking to the queues. Update, and in the
meantime open /admin/forex/withdraw directly.
Still stuck
Two things worth checking before you raise a ticket:
- The backend log, filtered to
FOREX,FOREX_DEPOSIT,FOREX_WITHDRAWAL,FOREX_INVESTMENTandFOREX_INVESTMENT_PROCESS. Every money movement in the addon logs the customer, the account, the amount and the outcome. /admin/system/cron, forprocessForexInvestments. Its live log broadcasts a line per investment as it works through them, which is the fastest way to see what settlement thinks it is doing.