Troubleshooting¶
Most run problems are recorded per-row in the job log — the admin run view, or the
fujin_job_log table (see Database schema). Each entry
has the row number, an action and a message. Start there.
A queued run sits at pending forever¶
Large imports (over syncRowThreshold, default 1000 rows) are queued to
Symfony Messenger. Nothing happens until a worker consumes them:
The same worker drains queued thumbnail jobs after an import. If you can't run a worker,
lower the threshold so the import runs synchronously, or use the CLI
(fujin:shuttle:run / run-profile).
"Run already in progress" / can't start a run¶
The duplicate-run guard refuses a second concurrent run of a
profile. If the previous run's worker died, its job stays active until its heartbeat_at goes
stale, after which it's reaped automatically and you can run again. To check:
SELECT HEX(id), status, heartbeat_at FROM fujin_job
WHERE profile_id = UNHEX('<profileHex>') AND status IN ('pending','running','stopping');
Categories / properties / custom fields aren't created¶
Auto-creation is governed by config toggles — all default on:
- categories →
autoCreateCategories - property groups/options →
autoCreatePropertyOptions - custom fields →
autoCreateCustomFields
If they're off, the referenced targets must already exist or the rows are skipped with a warning.
Manufacturers are skipped¶
Manufacturer auto-create is not implemented (autoCreateManufacturers
is reserved). A manufacturer value that doesn't match an existing manufacturer is skipped with
a warning. Pre-create manufacturers, or leave the column blank.
Variants skipped — "unknown parent"¶
A variant row whose parent_product_number doesn't resolve is skipped unless
autoCreateVariantParents is on (it creates a stub parent). Import the
parent products first, or enable the toggle.
Visibility / category columns parse wrong¶
- Multi-value cells split on the list delimiter (
|by default,listDelimiter). - Category paths split on the path delimiter (
>by default,categoryPathDelimiter). - A
visibilitycell isChannel:level; the level accepts numbers, slugs or admin labels — see the accepted spellings. An unknown level falls back to Visible everywhere.
If your data legitimately contains | or >, change the delimiter in config/profile.
Import is slow¶
- Media is usually the bottleneck. Try
rawmode, or turn media off to confirm. With media off the products path runs at full speed. - Use
--reindex=nonefor large cold loads and rebuild once afterwards (bin/console dal:refresh:index). - On a remote database, raise
concurrency. On localhost the insert path is MySQL-bound and concurrency barely moves the needle (see the flat sweep in Performance). - Profile a run with
FUJIN_PROF=1to get a per-stage breakdown:
Re-importing the same file does nothing¶
Imports are upserts keyed by product_number (or category_path, rule name, …).
Re-importing existing keys updates in place; importing the same unchanged data is effectively a
no-op. For the benchmark/cold-load path you need fresh keys.
Validate without writing¶
Use a dry run — it resolves IDs (and reports what would be created/skipped) but writes nothing:
Products imported but don't show up¶
If you ran with --reindex=none, rebuild the index: