commaai/openpilot · error · SCons.Errors.UserError
{t} is {size / (1024 * 1024):.1f} MiB, exceeding the {limit
Error message
{t} is {size / (1024 * 1024):.1f} MiB, exceeding the {limit / (1024 * 1024):.1f} MiB limit What it means
Raised by check_build_product_size, a SCons post-action on build products, when any produced file exceeds 50 MiB — the GitHub release asset upload cap that the comment cites. It aborts the build at the moment the oversized artifact appears, so a fat binary (usually with accidentally embedded debug info or a large static asset) cannot slip into a release.
Source
Thrown at SConstruct:347
def progress_function(node):
global progress_count
if progress_count >= progress_total:
return
progress_count = min(progress_count + progress_interval, progress_total)
progress = round(100. * progress_count / progress_total, 1)
sys.stderr.write("\rBuilding: %5.1f%%" % progress if sys.stderr.isatty() else "progress: %.1f\n" % progress)
if progress == 100. and sys.stderr.isatty():
sys.stderr.write("\n")
sys.stderr.flush()
Progress(progress_function, interval=progress_interval)
AddPostAction(BUILD_TARGETS or [Dir('.')], prune_cache_dir)
def check_build_product_size(target, source, env):
limit = 50 * 1024 * 1024 # GitHub max size
for t in target:
if hasattr(t, 'isfile') and t.isfile() and (size := os.path.getsize(t.abspath)) > limit:
raise SCons.Errors.UserError(f"{t} is {size / (1024 * 1024):.1f} MiB, exceeding the {limit / (1024 * 1024):.1f} MiB limit")
if not GetOption('extras'):
AddPostAction(list(build_product_nodes), Action(check_build_product_size, None))
View on GitHub (pinned to 516ec1e682)
Solutions
- Strip the binary in the link step (add -s or run strip via a post-action on that target) — debug info is the usual >50 MiB culprit.
- Check what bloated it: `size` / `nm --size-sort` / `objdump -h` on the artifact to find dominant symbols or sections.
- Move large assets out of the binary and into a separate downloaded resource so the executable stays under the cap.
- If you are intentionally building non-release/extras artifacts, build with scons --extras which skips this check (per `if not GetOption('extras')`).
Example fix
# before
env.Program('manager', objects) # unstripped, >50MiB -> post-action UserError
# after
env.Program('manager', objects, LINKFLAGS=['-s']) # stripped, under GitHub cap Defensive patterns
Strategy: validation
Validate before calling
# pre-link estimate: fail fast before a long build
import os, subprocess
size = os.path.getsize(str(node)) if os.path.exists(str(node)) else 0
assert size <= 50 * 1024 * 1024, f'{node} would exceed the 50 MiB release cap' Prevention
- Strip release binaries (LINKFLAGS=['-s'] or a strip post-action) by default.
- Keep large assets external to executables.
- Build non-release artifacts with --extras to bypass the check intentionally.
When it happens
Trigger: Any build product node (when not building with --extras) whose on-disk size passes 50 MiB: e.g. a release binary linked with -g or unstripped symbols, a bundled model/asset that grew past the cap, or duplicated static data linked into multiple products.
Common situations: Someone enables debug symbols or ASAN in a flag set used for release products; a new large model or firmware blob gets embedded; a linker config change stops stripping dead sections. CI release builds fail at the very end, after all compilation work.
Related errors
- Unexpected non-vendored library '{name}'
- invalid build metadata
- no product string in wrapped firmware
- bundled firmware is {expected_product!r}, expected version {
- cannot recover from the ROM bootloader without a config back
AI-assisted analysis of commaai/openpilot@516ec1e682 (2026-08-15).
Data as JSON: /api/errors/d04fe2f230bed2f7.
Report an issue: GitHub.