commaai/openpilot · error · SCons.Errors.UserError

Unexpected non-vendored library '{name}'

Error message

Unexpected non-vendored library '{name}'

What it means

Raised by _resolve_lib in the root SConstruct when a library named in LIBS is not found in any configured LIBPATH (as lib<name>.a/.so/.dylib) and is not in the small allowed_system_libs allowlist (dl, drm, gbm, m, pthread). This is openpilot's vendoring guard: every third-party dependency must either be built/vendored into the tree or explicitly allowlisted, so accidental dynamic dependencies on host packages fail the build with a UserError.

Source

Thrown at SConstruct:103

# e.g. apt-installed libusb. all libraries should either
# be distributed with all Linux distros and macOS, or
# vendored in commaai/dependencies.
allowed_system_libs = {
  "EGL", "GLESv2", "GL",
  "Qt5Charts", "Qt5Core", "Qt5Gui", "Qt5Widgets",
  "dl", "drm", "gbm", "m", "pthread",
}

def _resolve_lib(env, name):
  for d in env.Flatten(env.get('LIBPATH', [])):
    p = Dir(str(d)).abspath
    for ext in ('.a', '.so', '.dylib'):
      f = File(os.path.join(p, f'lib{name}{ext}'))
      if f.exists() or f.has_builder():
        return name
  if name in allowed_system_libs:
    return name
  raise SCons.Errors.UserError(f"Unexpected non-vendored library '{name}'")

def _libflags(target, source, env, for_signature):
  libs = []
  lp = env.subst('$LIBLITERALPREFIX')
  for lib in env.Flatten(env.get('LIBS', [])):
    if isinstance(lib, str):
      if os.sep in lib or lib.startswith('#'):
        libs.append(File(lib))
      elif lib.startswith('-') or (lp and lib.startswith(lp)):
        libs.append(lib)
      else:
        libs.append(_resolve_lib(env, lib))
    else:
      libs.append(lib)
  return _stripixes(env['LIBLINKPREFIX'], libs, env['LIBLINKSUFFIX'],
                    env['LIBPREFIXES'], env['LIBSUFFIXES'], env, env['LIBLITERALPREFIX'])

env = Environment(

View on GitHub (pinned to 516ec1e682)

Solutions

  1. Vendor/build the library inside the tree (typically under third_party/) and add its output directory to LIBPATH so lib<name>.a exists before linking.
  2. If the library genuinely must come from the system, add its name to allowed_system_libs in SConstruct — but upstream review will likely reject this for openpilot targets.
  3. Check for a typo in the LIBS entry; _resolve_lib only looks for files literally named lib<name>.<ext>.
  4. If a vendored lib is missing, re-run scons after checking that the third_party fetch/clone step succeeded (clean the relevant target and rebuild).

Example fix

# before
env.Append(LIBS=['avcodec'])  # not vendored, not allowlisted -> UserError

# after
# vendor it:
env.Append(CPPPATH=['#third_party/ffmpeg/include'])
env.Append(LIBPATH=['#third_party/ffmpeg/lib'])
env.Append(LIBS=['avcodec'])  # resolves to third_party/ffmpeg/lib/libavcodec.a
Defensive patterns

Strategy: validation

Validate before calling

# SConstruct-side: check every LIBS entry resolves before building
allowed = {'dl', 'drm', 'gbm', 'm', 'pthread'}
import os, glob
for lib in env.Flatten(env.get('LIBS', [])):
    if isinstance(lib, str) and os.sep not in lib and not lib.startswith(('-', '#')):
        found = any(glob.glob(os.path.join(str(d), f'lib{lib}.a')) for d in env.Flatten(env.get('LIBPATH', [])))
        assert found or lib in allowed, f'lib{lib} not vendored — add it to third_party or LIBPATH'

Try / catch

try:
    SConscript('my_component/SConscript')
except SCons.Errors.UserError as e:
    if 'non-vendored library' in str(e):
        print('Vendor the library under third_party/ and add its lib dir to LIBPATH')
    raise

Prevention

When it happens

Trigger: Adding a SConscript that does env.Append(LIBS=['avcodec']) (or any non-allowlisted name) without also vendoring/building the library into a directory on LIBPATH. Also triggered by typo'd library names, or by relying on system-installed dev packages that upstream refuses to link dynamically.

Common situations: Contributors porting new codec/IPC deps and assuming apt-installed libraries will be picked up; stale checkouts missing a vendored third_party lib after a fetch failure; CI environments where the prebuilt vendored libs were not downloaded.

Related errors


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