Skip to content

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:

bin/console messenger:consume async -vv

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:

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 visibility cell is Channel: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 raw mode, or turn media off to confirm. With media off the products path runs at full speed.
  • Use --reindex=none for 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=1 to get a per-stage breakdown:
    FUJIN_PROF=1 php -d error_log=/tmp/prof.log bin/console fujin:shuttle:run <csv> \
      --type=product --reindex=none
    

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:

bin/console fujin:shuttle:run products.csv --dry-run

Products imported but don't show up

If you ran with --reindex=none, rebuild the index:

bin/console dal:refresh:index