Skip to content

Numba: RuntimeError: no compiled object yet #6309

Description

@oyamad

=== Human text BEGIN ===

RuntimeError: no compiled object yet is raised by the following:

import quantecon as qe
grid = qe.simplex_grid(3, 4)
Full traceback
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
Cell In[1], line 2
      1 import quantecon as qe
----> 2 qe.simplex_grid(3, 4)

File /lib/python3.13/site-packages/numba/core/dispatcher.py:442, in _DispatcherBase._compile_for_args(self, *args, **kws)
    440             e.patch_message('\n'.join((str(e).rstrip(), help_msg)))
    441     # ignore the FULL_TRACEBACKS config, this needs reporting!
--> 442     raise e
    443 finally:
    444     self._types_active_call.clear()

File /lib/python3.13/site-packages/numba/core/dispatcher.py:375, in _DispatcherBase._compile_for_args(self, *args, **kws)
    373 return_val = None
    374 try:
--> 375     return_val = self.compile(tuple(argtypes))
    376 except errors.ForceLiteralArg as e:
    377     # Received request for compiler re-entry with the list of arguments
    378     # indicated by e.requested_args.
    379     # First, check if any of these args are already Literal-ized
    380     already_lit_pos = [i for i in e.requested_args
    381                        if isinstance(args[i], types.Literal)]

File /lib/python3.13/site-packages/numba/core/dispatcher.py:912, in Dispatcher.compile(self, sig)
    906 try:
    907     wasm_trace.log(
    908         "specialize",
    909         f"{self.py_func.__qualname__} for arguments "
    910         f"{tuple(map(str, args))}",
    911     )
--> 912     cres = self._compiler.compile(args, return_type)
    913 except errors.ForceLiteralArg as e:
    914     def folded(args, kws):

File /lib/python3.13/site-packages/numba/core/dispatcher.py:81, in _FunctionCompiler.compile(self, args, return_type)
     80 def compile(self, args, return_type):
---> 81     status, retval = self._compile_cached(args, return_type)
     82     if status:
     83         return retval

File /lib/python3.13/site-packages/numba/core/dispatcher.py:95, in _FunctionCompiler._compile_cached(self, args, return_type)
     92     pass
     94 try:
---> 95     retval = self._compile_core(args, return_type)
     96 except errors.TypingError as e:
     97     self._failed_cache[key] = e

File /lib/python3.13/site-packages/numba/core/dispatcher.py:108, in _FunctionCompiler._compile_core(self, args, return_type)
    105 flags = self._customize_flags(flags)
    107 impl = self._get_implementation(args, {})
--> 108 cres = compiler.compile_extra(self.targetdescr.typing_context,
    109                               self.targetdescr.target_context,
    110                               impl,
    111                               args=args, return_type=return_type,
    112                               flags=flags, locals=self.locals,
    113                               pipeline_class=self.pipeline_class)
    114 # Check typing error if object mode is used
    115 if cres.typing_error is not None and not flags.enable_pyobject:

File /lib/python3.13/site-packages/numba/core/compiler.py:739, in compile_extra(typingctx, targetctx, func, args, return_type, flags, locals, library, pipeline_class)
    715 """Compiler entry point
    716 
    717 Parameter
   (...)    735     compiler pipeline
    736 """
    737 pipeline = pipeline_class(typingctx, targetctx, library,
    738                           args, return_type, flags, locals)
--> 739 return pipeline.compile_extra(func)

File /lib/python3.13/site-packages/numba/core/compiler.py:439, in CompilerBase.compile_extra(self, func)
    437 self.state.lifted = ()
    438 self.state.lifted_from = None
--> 439 return self._compile_bytecode()

File /lib/python3.13/site-packages/numba/core/compiler.py:505, in CompilerBase._compile_bytecode(self)
    501 """
    502 Populate and run pipeline for bytecode input
    503 """
    504 assert self.state.func_ir is None
--> 505 return self._compile_core()

File /lib/python3.13/site-packages/numba/core/compiler.py:481, in CompilerBase._compile_core(self)
    479 except Exception as e:
    480     if not isinstance(e, errors.NumbaError):
--> 481         raise e
    482     self.state.status.fail_reason = e
    483     if is_final_pipeline:

File /lib/python3.13/site-packages/numba/core/compiler.py:473, in CompilerBase._compile_core(self)
    471 res = None
    472 try:
--> 473     pm.run(self.state)
    474     if self.state.cr is not None:
    475         break

File /lib/python3.13/site-packages/numba/core/compiler_machinery.py:401, in PassManager.run(self, state)
    399 except Exception as e:
    400     if not isinstance(e, errors.NumbaError):
--> 401         raise e
    402     msg = "Failed in %s mode pipeline (step: %s)" % \
    403         (self.pipeline_name, pass_desc)
    404     patched_exception = self._patch_error(msg, e)

File /lib/python3.13/site-packages/numba/core/compiler_machinery.py:394, in PassManager.run(self, state)
    392 pass_inst = _pass_registry.get(pss).pass_inst
    393 if isinstance(pass_inst, CompilerPass):
--> 394     self._runPass(idx, pass_inst, state)
    395 else:
    396     raise BaseException("Legacy pass in use")

File /lib/python3.13/site-packages/numba/core/compiler_lock.py:35, in _CompilerLock.__call__.<locals>._acquire_compile_lock(*args, **kwargs)
     32 @functools.wraps(func)
     33 def _acquire_compile_lock(*args, **kwargs):
     34     with self:
---> 35         return func(*args, **kwargs)

File /lib/python3.13/site-packages/numba/core/compiler_machinery.py:322, in PassManager._runPass(self, index, pss, internal_state)
    320     mutated |= check(pss.run_initialization, internal_state)
    321 with SimpleTimer() as pass_time:
--> 322     mutated |= check(pss.run_pass, internal_state)
    323 with SimpleTimer() as finalize_time:
    324     mutated |= check(pss.run_finalizer, internal_state)

File /lib/python3.13/site-packages/numba/core/compiler_machinery.py:283, in PassManager._runPass.<locals>.check(func, compiler_state)
    282 def check(func, compiler_state):
--> 283     mangled = func(compiler_state)
    284     if mangled not in (True, False):
    285         msg = ("CompilerPass implementations should return True/False. "
    286                "CompilerPass with name '%s' did not.")

File /lib/python3.13/site-packages/numba/core/typed_passes.py:114, in BaseTypeInference.run_pass(self, state)
    108 """
    109 Type inference and legalization
    110 """
    111 with fallback_context(state, 'Function "%s" failed type inference'
    112                       % (state.func_id.func_name,)):
    113     # Type inference
--> 114     typemap, return_type, calltypes, errs = type_inference_stage(
    115         state.typingctx,
    116         state.targetctx,
    117         state.func_ir,
    118         state.args,
    119         state.return_type,
    120         state.locals,
    121         raise_errors=self._raise_errors)
    122     state.typemap = typemap
    123     # save errors in case of partial typing

File /lib/python3.13/site-packages/numba/core/typed_passes.py:95, in type_inference_stage(typingctx, targetctx, interp, args, return_type, locals, raise_errors)
     93     infer.build_constraint()
     94     # return errors in case of partial typing
---> 95     errs = infer.propagate(raise_errors=raise_errors)
     96     typemap, restype, calltypes = infer.unify(raise_errors=raise_errors)
     98 return _TypingResults(typemap, restype, calltypes, errs)

File /lib/python3.13/site-packages/numba/core/typeinfer.py:1075, in TypeInferer.propagate(self, raise_errors)
   1072 oldtoken = newtoken
   1073 # Errors can appear when the type set is incomplete; only
   1074 # raise them when there is no progress anymore.
-> 1075 errors = self.constraints.propagate(self)
   1076 newtoken = self.get_state_token()
   1077 self.debug.propagate_finished()

File /lib/python3.13/site-packages/numba/core/typeinfer.py:160, in ConstraintNetwork.propagate(self, typeinfer)
    157 with typeinfer.warnings.catch_warnings(filename=loc.filename,
    158                                        lineno=loc.line):
    159     try:
--> 160         constraint(typeinfer)
    161     except ForceLiteralArg as e:
    162         errors.append(e)

File /lib/python3.13/site-packages/numba/core/typeinfer.py:572, in CallConstraint.__call__(self, typeinfer)
    569     fnty = typevars[self.func].getone()
    570 with new_error_context("resolving callee type: {fnty}",
    571                        fnty=fnty):
--> 572     self.resolve(typeinfer, typevars, fnty)

File /lib/python3.13/site-packages/numba/core/typeinfer.py:595, in CallConstraint.resolve(self, typeinfer, typevars, fnty)
    593     fnty = fnty.instance_type
    594 try:
--> 595     sig = typeinfer.resolve_call(fnty, pos_args, kw_args)
    596 except ForceLiteralArg as e:
    597     # Adjust for bound methods
    598     folding_args = ((fnty.this,) + tuple(self.args)
    599                     if isinstance(fnty, types.BoundFunction)
    600                     else self.args)

File /lib/python3.13/site-packages/numba/core/typeinfer.py:1569, in TypeInferer.resolve_call(self, fnty, pos_args, kw_args)
   1566     return sig
   1567 else:
   1568     # Normal non-recursive call
-> 1569     return self.context.resolve_function_type(fnty, pos_args, kw_args)

File /lib/python3.13/site-packages/numba/core/typing/context.py:279, in BaseContext.resolve_function_type(self, func, args, kws)
    277 # Prefer user definition first
    278 try:
--> 279     res = self._resolve_user_function_type(func, args, kws)
    280 except errors.TypingError as e:
    281     # Capture any typing error
    282     last_exception = e

File /lib/python3.13/site-packages/numba/core/typing/context.py:335, in BaseContext._resolve_user_function_type(self, func, args, kws, literals)
    331         return self.resolve_function_type(func_type, args, kws)
    333 if isinstance(func, types.Callable):
    334     # XXX fold this into the __call__ attribute logic?
--> 335     return func.get_call_type(self, args, kws)

File /lib/python3.13/site-packages/numba/core/types/functions.py:541, in Dispatcher.get_call_type(self, context, args, kws)
    534 def get_call_type(self, context, args, kws):
    535     """
    536     Resolve a call to this dispatcher using the given argument types.
    537     A signature returned and it is ensured that a compiled specialization
    538     is available for it.
    539     """
    540     template, pysig, args, kws = \
--> 541         self.dispatcher.get_call_template(args, kws)
    542     sig = template(context).apply(args, kws)
    543     if sig:

File /lib/python3.13/site-packages/numba/core/dispatcher.py:318, in _DispatcherBase.get_call_template(self, args, kws)
    316 # Ensure an overload is available
    317 if self._can_compile:
--> 318     self.compile(tuple(args))
    320 # Create function type for typing
    321 func_name = self.py_func.__name__

File /lib/python3.13/site-packages/numba/core/dispatcher.py:919, in Dispatcher.compile(self, sig)
    917         raise e.bind_fold_arguments(folded)
    918     self.add_overload(cres)
--> 919 self._cache.save_overload(sig, cres)
    920 return cres.entry_point

File /lib/python3.13/site-packages/numba/core/caching.py:777, in Cache.save_overload(self, sig, data)
    773 """
    774 Save the data for the given signature in the cache.
    775 """
    776 with self._guard_against_spurious_io_errors():
--> 777     self._save_overload(sig, data)

File /lib/python3.13/site-packages/numba/core/caching.py:786, in Cache._save_overload(self, sig, data)
    784 self._impl.locator.ensure_cache_path()
    785 key = self._index_key(sig, data.codegen)
--> 786 data = self._impl.reduce(data)
    787 self._cache_file.save(key, data)

File /lib/python3.13/site-packages/numba/core/caching.py:505, in CompileResultCacheImpl.reduce(self, cres)
    501 def reduce(self, cres):
    502     """
    503     Returns a serialized CompileResult
    504     """
--> 505     return cres._reduce()

File /lib/python3.13/site-packages/numba/core/compiler.py:200, in CompileResult._reduce(self)
    196 def _reduce(self):
    197     """
    198     Reduce a CompileResult to picklable components.
    199     """
--> 200     libdata = self.library.serialize_using_object_code()
    201     # Make it (un)picklable efficiently
    202     typeann = str(self.type_annotation)

File /lib/python3.13/site-packages/numba/core/codegen.py:956, in CPUCodeLibrary.serialize_using_object_code(self)
    953 data = (self._get_compiled_object(),
    954         self._get_module_for_linking().as_bitcode())
    955 if sys.platform == "emscripten":
--> 956     dependencies = self._serialize_wasm_linking_libraries()
    957     wasm_trace.log(
    958         "cache",
    959         f"saving {len(dependencies)} linking module(s) with "
    960         f"{self.name!r}",
    961     )
    962     return (self.name, 'object', data, dependencies)

File /lib/python3.13/site-packages/numba/core/codegen.py:984, in CPUCodeLibrary._serialize_wasm_linking_libraries(self)
    981     states.append((library.name, 'object', data))
    983 for library in self._linking_libraries:
--> 984     visit(library)
    985 return tuple(states)

File /lib/python3.13/site-packages/numba/core/codegen.py:978, in CPUCodeLibrary._serialize_wasm_linking_libraries.<locals>.visit(library)
    975 for dependency in library._linking_libraries:
    976     visit(dependency)
    977 data = (
--> 978     library._get_compiled_object(),
    979     library._get_module_for_linking().as_bitcode(),
    980 )
    981 states.append((library.name, 'object', data))

File /lib/python3.13/site-packages/numba/core/codegen.py:632, in CodeLibrary._get_compiled_object(self)
    630     raise ValueError("object caching not enabled in %s" % (self,))
    631 if self._compiled_object is None:
--> 632     raise RuntimeError("no compiled object yet for %s" % (self,))
    633 return self._compiled_object

RuntimeError: no compiled object yet for <Library 'comb_jit' at 0xa208810>
...
RuntimeError: no compiled object yet for <Library 'f' at 0x936acb8>

The following is a (quantecon-free) MWE generated by Claude Code Fable 5:

=== Human text END ===


=== AI text (with minor edits) BEGIN ===

Symptom

With a warm persistent cache, the first compilation of a cache=True function that calls another cached function crashes at cache-save time:

File .../numba/core/codegen.py:978, in _serialize_wasm_linking_libraries.<locals>.visit
File .../numba/core/codegen.py:632, in CodeLibrary._get_compiled_object
RuntimeError: no compiled object yet for <Library 'f' at 0x...>

Root cause

0006-persist-wasm-code-cache-in-jupyterlite.patch adds _serialize_wasm_linking_libraries, which walks the library's _linking_libraries and calls _get_compiled_object() on each. But a library restored from the cache no longer has its object: mainline numba's _object_getbuffer_hook hands the buffer to the engine and sets self._compiled_object = None (consumed). So the crash occurs exactly when a fresh compile (cache miss) links a dispatcher that was restored (cache hit) in the same session. Fresh+fresh and hit+hit are both fine, which is why the bug is easy to miss in testing.

Note the failure is self-perpetuating: the save that would cache the dependent function is the operation that crashes, so the dependent can never become a cache hit, and the crash recurs in every warm session.

Minimal repro

cachemwe.py (any module on /drive):

from numba import njit

@njit(cache=True)
def f(x):
    return x + 1

@njit(cache=True)
def g(x):
    return f(x) * 2
  • Session 1: import cachemwe; cachemwe.f(1) — and nothing else. (Wait ~10 s before reloading; see "Secondary issue" below.)
  • Reload the page (fresh kernel, persistent cache retained).
  • Session 2: cachemwe.f(1) → cache hit (verify via f.stats.cache_hits); then cachemwe.g(1) → RuntimeError above.

Observed: f: 2 | f hits: 1, then the crash on g(1). Control: pointing NUMBA_CACHE_DIR at an empty directory (all misses) makes the same code work.

Secondary issue

Cache writes shortly before a page reload are sometimes lost (/drive is backed by the asynchronous Contents API), so freshly written .nbi/.nbc files may not survive the reload. This makes the primary bug intermittent to reproduce; a short wait before reloading avoids it.

Possible fixes

  • Don't consume _compiled_object on Emscripten (retain the bytes after the getbuffer hook), at some memory cost; or
  • have the save path re-reduce restored dependencies from their own cache entries instead of from the in-memory library; or
  • skip already-loaded modules in the walk, mirroring the tolerance the restore path (_restore_wasm_linking_libraries) already has — with care that a later cold session can still resolve the dependency at load time.

Environment

JupyterLite + xeus-python, emscripten-forge numba build (patch set present). Verified in-session:

sys.platform : emscripten
python       : 3.13.1
numba        : 0.66.0
llvmlite     : 0.48.0
numpy        : 2.4.6
scipy        : 1.18.0
intp width   : 32 bit
cache dir    : /drive/.cache/numba   (patch 0006 default; no NUMBA_CACHE_DIR override)
wasm build   : patched (numba.core.wasm_trace present)
/drive mount : True

🤖 Generated with Claude Code (Claude Fable 5)

=== AI text EMD ===

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions