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

  1. 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.
  2. Check what bloated it: `size` / `nm --size-sort` / `objdump -h` on the artifact to find dominant symbols or sections.
  3. Move large assets out of the binary and into a separate downloaded resource so the executable stays under the cap.
  4. 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

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


AI-assisted analysis of commaai/openpilot@516ec1e682 (2026-08-15). Data as JSON: /api/errors/d04fe2f230bed2f7. Report an issue: GitHub.