The errors bjs inject actually emits, in the order you're most likely to see them, with what they mean and what to do.
"You must be logged in to submit an injection."
bjs inject is auth-gated. Every submission is tied to a user, so the CLI refuses to run without a valid session token in ~/.bjs/config.json.
What to do: run bjs login. Your browser opens to the OAuth flow on babylonjsmarket.com; approve and you're done. The token is good for 7 days (the existing JWT lifetime in @babylonjsmarket/cli). When it expires mid-session, this same error appears — re-run bjs login to refresh.
"Rate limit"
You've submitted too many injections in too short a window. The cap is 5 submissions per hour per user by default, configured server-side via the SUBMISSION_HOURLY_LIMIT environment variable.
What to do: wait an hour and retry. If you have a legitimate need to push more (a batch port of a dozen components, say), contact the operator and they can lift the cap for your account or raise the global ceiling for a window.
"Payload too large"
The submission API rejects payloads that exceed the per-file or total size caps:
- 256 KB per file. No single file in the submission may be larger.
- 2 MB total. The sum of all file contents must be under this ceiling.
- No binaries in v1. Every file in the payload must be valid UTF-8 text. Images, audio, fonts, or
.glbfiles are rejected at validation time.
What to do: if a single file is the culprit, look hard at it — components shouldn't be that large. Split the file, move data out of the source, or move binary assets out of the component folder. v1 is text-only on purpose; richer asset payloads are a planned follow-up.
"the arcade library is not checked out at …"
(Same shape for viz.)
bjs inject writes into the target library's working tree only in operator mode (running locally against a project / library checkout). Members don't see this error — bjs inject runs against a tmpdir and ships the diff to the API. If you do see it, you're running the operator-mode wrapper directly.
What to do (operator-mode runs): make sure the target tree is on disk — the project's src/components/ for arcade, or the @babylonjsmarket/viz checkout for viz. The tool only checks the target you're using on this run.
What to do (members): you shouldn't be hitting this — bjs inject doesn't need a local library checkout. If you're seeing it from bjs inject, file a bug.
"Auto-detect disagrees across seeds: …"
You ran bjs inject Foo Bar and the closure of one of them tipped to a different target. The tool refuses to write a partial mix.
What to do: look at why the targets diverge. Usually one seed is in the wrong target — a panel-only seed that you tried to inject alongside a gameplay seed. Split the run:
Or, if you know what you're doing, force the call:
--target doesn't make the mismatch correct — it just makes the tool stop checking. Read the dry-run output carefully.
"--move requires --confirm …"
--move deletes your project copy of the component and strips the line from your project's src/registry.ts. That's destructive. --confirm is the safety rail.
What to do: add --confirm.
"--move and --dry-run are mutually exclusive."
A dry-run move would print "I would delete these files" without doing anything, which gives you no signal you didn't already have from the regular dry-run plan. The combination has no useful meaning, so the tool refuses it.
What to do: do the dry-run first to confirm the plan, then run with --move --confirm once you're happy.
"viz/<layer>/<File> already exists — pass --force to overwrite."
The viz target file is already there from a previous inject. The tool refuses to clobber it by default.
What to do: decide which copy you want. If yours is newer, pass --force:
If the existing copy in viz is newer (maybe someone else patched it), pull their changes back into your project before re-running.
The same protection exists for arcade:
…with the same fix.
"Could not find source for "<Name>". Looked at …"
The tool expected your component at <cwd>/src/components/<Name>/ and it's not there.
What to do: either run the command from the project root that contains src/components/<Name>/, or pass --source to point at the seed:
Remember --source skips the transitive closure walk — it injects just that seed and trusts you.
"Could not find 'ARCADE_COMPONENT_REGISTRY' marker — add resolvers manually for: …"
The tool copied your component into src/components/Bouncer/ but couldn't find the ARCADE_COMPONENT_REGISTRY: Record<string, LazyComponentResolver> = { marker in the project's src/registry.ts to insert the lazy resolver into.
This is a warn-but-don't-fail behaviour. The files are already in the right place; only the registry patch was skipped.
What to do: open the project's src/registry.ts and add the line by hand:
…inside the ARCADE_COMPONENT_REGISTRY object. Then commit. The same warning shape applies to viz barrels:
…with the same fix: add export * from './MyDebugger.viz'; to the file by hand.
"Unknown --target …" / "Unknown --layer …"
Self-explanatory. The valid values for each flag are listed in target selection.
"--source applies to a single seed; pass one NAME with --source."
--source overrides where the tool looks for the seed, and pointing one --source at multiple names doesn't make sense.
What to do: run one seed at a time when using --source:
"No component names given."
You ran bjs inject with no positional args.
What to do: pass at least one name.
Foreign-library imports
When your seed imports a name from @babylonjsmarket/arcade (or viz, or the other one), and that name is not co-injected in this run, the tool leaves the import alone. The published file ends up with an @babylonjsmarket/arcade/<Sibling> import that resolves through npm — fine if the sibling actually lives there, broken if it doesn't.
There's no error for this — it's a class of issue the tool can't reliably detect at inject time. Watch your dry-run output for imports that look surprising, and read round-trip with eject for the contract that keeps imports clean.
Dry-run shows zero changes
If bjs inject Foo --dry-run runs but lists no + lines and no patched lines, the seed is already in the target library — every file would be a duplicate (refused without --force), and the registry line is already there (the patch is idempotent).
What to do: if this is what you wanted to confirm, you're done. If you wanted to update the existing copy with new changes from your project, pass --force:
What's next
If your error isn't in this list, the next stop is the source: packages/cli/src/lib/inject/engine.ts is small and readable. Every error message in the tool is grep-able to the line that produced it.
For the larger publishing flow, see publish as a product.