Troubleshooting
The dist won't import / "bad marshal data"
The protected dist was almost certainly built with a different CPython version than the one running it. The marshal/bytecode format is version-specific. Rebuild with the same Python version you ship for, and make sure Obfy is installed into that interpreter.
obfy build can't import the runtime
obfy build needs the bundled runtime importable from the --python you pass.
Make sure Obfy is installed into that interpreter (the runtime ships with the
obfy package):
python -m pip install obfy # using the same interpreter you pass to --python
Code breaks only at --level 4
Level 4 renames public names across the whole tree, which breaks code that looks
names up dynamically (by string, getattr, or framework auto-discovery). Exclude
the affected files so they stay as plain source, or drop to --level 3:
obfy build --src ./app --out ./dist --level 4 --exclude "*/plugins/*"
See Excluding files.
The dist refuses to run
If you built with --license, the runtime enforces its terms locally. Common
causes:
- Expired — the
expiresdate has passed (andanti_rollbackblocks clock tricks). - Wrong machine — a
machines,hostnames, ordisksbinding doesn't match the current host. - Anti-debug — built with
--anti-debugand a tracer/debugger is attached. - Anti-tamper — built with
--anti-tamperand the on-disk loader ormanifest.jsonwas modified.
A secret (.env, key) ended up in the dist
Every non-.py file under --src is copied into the dist. Point --src at your
code package rather than your repo root, or build from a code-only staging tree.
I can't run obfy build — not authorized
Your machine isn't authorized, or you're out of seats. Run obfy login and
obfy register to claim a seat slot (logging in alone isn't enough), then check
obfy whoami. Revoke an unused device from the portal's Devices page if you've
hit the per-seat machine limit. On an air-gapped machine, authorize with an offline
activation (obfy register --offline → obfy activate <file>) instead. See
Seats and devices.