Watch at EaseStories. Answers. Perspective.

Technology · PRACTICAL GUIDE

Python says “bad magic number” in a .pyc? Prove the runtime and source boundary

Do not delete every cache or edit the header. First identify the exact file Python loaded, the interpreter that is running, and whether usable source exists.

Diagram identifying the loaded pyc, runtime and magic bytes
Original illustration: prove the incompatible boundary first. Watch at Ease

Do not delete every cache or edit the header. First identify the exact file Python loaded, the interpreter that is running, and whether usable source exists.

The pyc header begins with interpreter-specific magic bytes. importlib.util.MAGIC_NUMBER exposes the current interpreter value.

1. Capture the failing file and interpreter

Save the complete traceback before cleanup. Record sys.executable, sys.version, sys.implementation.cache_tag, the working directory, environment variables that affect imports, and the failing module path. A shell named python may not be the interpreter used by a service, IDE, task runner or embedded application.

Use import discovery or the traceback to locate the exact file. Check sys.path order, virtual-environment activation, mounted volumes and copied deployment directories. The error identifies incompatible bytecode; it does not prove every pyc on the machine is wrong.

2. Compare the header without executing it

Open the suspect file as data and read its first four bytes. Compare them with importlib.util.MAGIC_NUMBER from the interpreter that actually fails. Do not import or execute untrusted bytecode merely to inspect it.

A mismatch proves the file is not bytecode for this interpreter build. A match is not a safety or integrity certificate: the rest of the header, marshalled code or source relationship can still be invalid or corrupt.

3. Classify source-backed and pyc-only cases

If a matching .py source file exists and is authoritative, preserve the old pyc for evidence, remove only the exact incompatible cache, and let the intended interpreter regenerate it. Confirm the process can write the cache directory; lack of a new pyc alone does not mean import failed.

If the deployment is pyc-only, deleting it removes the program rather than refreshing a cache. Obtain the source or rebuild output from the owner with the target interpreter. Do not change the magic bytes to force loading: bytecode opcodes and marshal format may also differ.

4. Regenerate or rebuild the correct artifact

For an installed package, compare the file with package metadata and rebuild or reinstall into a clean environment from a trusted wheel or source. PyPA explains that wheels normally omit pyc and installers generate it locally, so foreign cache files inside an artifact are a packaging clue.

For containers and serverless bundles, rebuild from a clean context under the exact runtime used in production. Exclude host __pycache__ directories from the build context, and do not reuse a mounted cache across interpreter upgrades.

5. Verify imports and prevent recurrence

Restart the real entry point and verify the same executable, import origin and module version. Confirm representative imports in a fresh process, then compare generated cache paths and tags with the intended runtime.

Record the failing path, old and current magic bytes, runtime identity, source status, rebuild source and verification. Add a clean-build test that rejects pyc-only or foreign-cache artifacts unless that compatibility is intentional and proven.

Decision diagram for source-backed, pyc-only and package recovery
Original illustration: rebuild instead of patching headers. Watch at Ease