`nbdev_build_docs` gets stuck on converting the last notebook

Hello, I haven’t faced this issue before but recently when I run the command nbdev_build_docs or make_docs it takes over 10 minutes to generate the docs.

To see if I could replicate the issue, I created a new repo from the template.

Contents on index.ipynb

Contents of 00_core.ipynb
image


I am not sure what is going wrong over here. Can anyone help me?

1 Like

If you interrupt it, what’s the stack trace show it’s doing?

Apologies if it’s a different issue, but I was running into a similar issue last week and traced it back to a long training function call which was timing out (wasn’t sure how to disable it, but I haven’t looked back to the project).

Here is the entire stack trace

(base) devengqc@17-CN0065CL-1:~/git/public/test_nbdev$ make -B all
nbdev_build_lib
touch foo
Converted 00_core.ipynb.
Converted index.ipynb.
nbdev_build_docs
touch docs
converting: /home/devengqc/git/public/test_nbdev/00_core.ipynb
converting: /home/devengqc/git/public/test_nbdev/index.ipynb
^CProcess ForkProcess-9:
Process ForkProcess-7:
Process ForkProcess-8:
Process ForkProcess-6:
Process ForkProcess-4:
Process ForkProcess-5:
Traceback (most recent call last):
  File "/home/devengqc/miniconda3/lib/python3.8/multiprocessing/process.py", line 315, in _bootstrap
    self.run()
  File "/home/devengqc/miniconda3/lib/python3.8/multiprocessing/process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "/home/devengqc/miniconda3/lib/python3.8/concurrent/futures/process.py", line 233, in _process_worker
    call_item = call_queue.get(block=True)
  File "/home/devengqc/miniconda3/lib/python3.8/multiprocessing/queues.py", line 96, in get
    with self._rlock:
  File "/home/devengqc/miniconda3/lib/python3.8/multiprocessing/synchronize.py", line 95, in __enter__
    return self._semlock.__enter__()
KeyboardInterrupt
Traceback (most recent call last):
  File "/home/devengqc/miniconda3/lib/python3.8/multiprocessing/process.py", line 315, in _bootstrap
    self.run()
  File "/home/devengqc/miniconda3/lib/python3.8/multiprocessing/process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "/home/devengqc/miniconda3/lib/python3.8/concurrent/futures/process.py", line 233, in _process_worker
    call_item = call_queue.get(block=True)
  File "/home/devengqc/miniconda3/lib/python3.8/multiprocessing/queues.py", line 96, in get
    with self._rlock:
  File "/home/devengqc/miniconda3/lib/python3.8/multiprocessing/synchronize.py", line 95, in __enter__
    return self._semlock.__enter__()
KeyboardInterrupt
Traceback (most recent call last):
  File "/home/devengqc/miniconda3/lib/python3.8/multiprocessing/process.py", line 315, in _bootstrap
    self.run()
  File "/home/devengqc/miniconda3/lib/python3.8/multiprocessing/process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "/home/devengqc/miniconda3/lib/python3.8/concurrent/futures/process.py", line 233, in _process_worker
    call_item = call_queue.get(block=True)
  File "/home/devengqc/miniconda3/lib/python3.8/multiprocessing/queues.py", line 96, in get
    with self._rlock:
  File "/home/devengqc/miniconda3/lib/python3.8/multiprocessing/synchronize.py", line 95, in __enter__
    return self._semlock.__enter__()
KeyboardInterrupt
Traceback (most recent call last):
  File "/home/devengqc/miniconda3/lib/python3.8/multiprocessing/process.py", line 315, in _bootstrap
    self.run()
  File "/home/devengqc/miniconda3/lib/python3.8/multiprocessing/process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "/home/devengqc/miniconda3/lib/python3.8/concurrent/futures/process.py", line 233, in _process_worker
    call_item = call_queue.get(block=True)
  File "/home/devengqc/miniconda3/lib/python3.8/multiprocessing/queues.py", line 96, in get
    with self._rlock:
  File "/home/devengqc/miniconda3/lib/python3.8/multiprocessing/synchronize.py", line 95, in __enter__
    return self._semlock.__enter__()
KeyboardInterrupt
Traceback (most recent call last):
  File "/home/devengqc/miniconda3/lib/python3.8/multiprocessing/process.py", line 315, in _bootstrap
    self.run()
  File "/home/devengqc/miniconda3/lib/python3.8/multiprocessing/process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "/home/devengqc/miniconda3/lib/python3.8/concurrent/futures/process.py", line 233, in _process_worker
    call_item = call_queue.get(block=True)
  File "/home/devengqc/miniconda3/lib/python3.8/multiprocessing/queues.py", line 96, in get
    with self._rlock:
  File "/home/devengqc/miniconda3/lib/python3.8/multiprocessing/synchronize.py", line 95, in __enter__
    return self._semlock.__enter__()
KeyboardInterrupt
Traceback (most recent call last):
  File "/home/devengqc/miniconda3/lib/python3.8/multiprocessing/process.py", line 315, in _bootstrap
    self.run()
  File "/home/devengqc/miniconda3/lib/python3.8/multiprocessing/process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "/home/devengqc/miniconda3/lib/python3.8/concurrent/futures/process.py", line 233, in _process_worker
    call_item = call_queue.get(block=True)
  File "/home/devengqc/miniconda3/lib/python3.8/multiprocessing/queues.py", line 97, in get
    res = self._recv_bytes()
  File "/home/devengqc/miniconda3/lib/python3.8/multiprocessing/connection.py", line 216, in recv_bytes
    buf = self._recv_bytes(maxlength)
  File "/home/devengqc/miniconda3/lib/python3.8/multiprocessing/connection.py", line 414, in _recv_bytes
    buf = self._recv(4)
  File "/home/devengqc/miniconda3/lib/python3.8/multiprocessing/connection.py", line 379, in _recv
    chunk = read(handle, remaining)
KeyboardInterrupt
Traceback (most recent call last):
  File "/home/devengqc/miniconda3/bin/nbdev_build_docs", line 8, in <module>
    sys.exit(nbdev_build_docs())
  File "/home/devengqc/miniconda3/lib/python3.8/site-packages/fastcore/script.py", line 113, in _f
    tfunc(**merge(args, args_from_prog(func, xtra)))
  File "/home/devengqc/miniconda3/lib/python3.8/site-packages/nbdev/export2html.py", line 648, in nbdev_build_docs
    notebook2html(fname=fname, force_all=force_all, n_workers=n_workers, pause=pause)
  File "/home/devengqc/miniconda3/lib/python3.8/site-packages/nbdev/export2html.py", line 534, in notebook2html
    passed = parallel(_notebook2html, files, n_workers=n_workers, cls=cls,
  File "/home/devengqc/miniconda3/lib/python3.8/site-packages/fastcore/parallel.py", line 123, in parallel
    return L(r)
  File "/home/devengqc/miniconda3/lib/python3.8/site-packages/fastcore/foundation.py", line 97, in __call__
    return super().__call__(x, *args, **kwargs)
  File "/home/devengqc/miniconda3/lib/python3.8/site-packages/fastcore/foundation.py", line 105, in __init__
    items = listify(items, *rest, use_list=use_list, match=match)
  File "/home/devengqc/miniconda3/lib/python3.8/site-packages/fastcore/basics.py", line 59, in listify
    elif is_iter(o): res = list(o)
  File "/home/devengqc/miniconda3/lib/python3.8/concurrent/futures/process.py", line 484, in _chain_from_iterable_of_lists
    for element in iterable:
  File "/home/devengqc/miniconda3/lib/python3.8/concurrent/futures/_base.py", line 619, in result_iterator
    yield fs.pop().result()
  File "/home/devengqc/miniconda3/lib/python3.8/concurrent/futures/_base.py", line 439, in result
    self._condition.wait(timeout)
  File "/home/devengqc/miniconda3/lib/python3.8/threading.py", line 302, in wait
    waiter.acquire()
KeyboardInterrupt
make: *** [Makefile:18: docs] Interrupt

Ah sorry it uses parallel processing by default which makes the stack trace useless!

Can you please run it again, but this time with --n_workers 0 ?

Sure, here it is

(base) devengqc@17-CN0065CL-1:~/git/public/test_nbdev$ nbdev_build_docs --n_workers 0
converting: /home/devengqc/git/public/test_nbdev/index.ipynb
^CTraceback (most recent call last):
  File "/home/devengqc/miniconda3/bin/nbdev_build_docs", line 8, in <module>
    sys.exit(nbdev_build_docs())
  File "/home/devengqc/miniconda3/lib/python3.8/site-packages/fastcore/script.py", line 113, in _f
    tfunc(**merge(args, args_from_prog(func, xtra)))
  File "/home/devengqc/miniconda3/lib/python3.8/site-packages/nbdev/export2html.py", line 648, in nbdev_build_docs
    notebook2html(fname=fname, force_all=force_all, n_workers=n_workers, pause=pause)
  File "/home/devengqc/miniconda3/lib/python3.8/site-packages/nbdev/export2html.py", line 534, in notebook2html
    passed = parallel(_notebook2html, files, n_workers=n_workers, cls=cls,
  File "/home/devengqc/miniconda3/lib/python3.8/site-packages/fastcore/parallel.py", line 123, in parallel
    return L(r)
  File "/home/devengqc/miniconda3/lib/python3.8/site-packages/fastcore/foundation.py", line 97, in __call__
    return super().__call__(x, *args, **kwargs)
  File "/home/devengqc/miniconda3/lib/python3.8/site-packages/fastcore/foundation.py", line 105, in __init__
    items = listify(items, *rest, use_list=use_list, match=match)
  File "/home/devengqc/miniconda3/lib/python3.8/site-packages/fastcore/basics.py", line 59, in listify
    elif is_iter(o): res = list(o)
  File "/home/devengqc/miniconda3/lib/python3.8/site-packages/nbdev/export2html.py", line 510, in _notebook2html
    convert_nb(fname, cls=cls, template_file=template_file, exporter=exporter, dest=dest, execute=execute)
  File "/home/devengqc/miniconda3/lib/python3.8/site-packages/nbdev/export2html.py", line 499, in convert_nb
    if execute: nb = execute_nb(nb, mod=mod)
  File "/home/devengqc/miniconda3/lib/python3.8/site-packages/nbdev/export2html.py", line 407, in execute_nb
    ep.preprocess(pnb, metadata)
  File "/home/devengqc/miniconda3/lib/python3.8/site-packages/nbconvert/preprocessors/execute.py", line 89, in preprocess
    self.preprocess_cell(cell, resources, index)
  File "/home/devengqc/miniconda3/lib/python3.8/site-packages/nbdev/export2html.py", line 382, in preprocess_cell
    return super().preprocess_cell(cell, resources, index)
  File "/home/devengqc/miniconda3/lib/python3.8/site-packages/nbconvert/preprocessors/execute.py", line 110, in preprocess_cell
    cell = self.execute_cell(cell, index, store_history=True)
  File "/home/devengqc/miniconda3/lib/python3.8/site-packages/nbclient/util.py", line 85, in wrapped
    return just_run(coro(*args, **kwargs))
  File "/home/devengqc/miniconda3/lib/python3.8/site-packages/nbclient/util.py", line 60, in just_run
    return loop.run_until_complete(coro)
  File "/home/devengqc/miniconda3/lib/python3.8/asyncio/base_events.py", line 603, in run_until_complete
    self.run_forever()
  File "/home/devengqc/miniconda3/lib/python3.8/asyncio/base_events.py", line 570, in run_forever
    self._run_once()
  File "/home/devengqc/miniconda3/lib/python3.8/asyncio/base_events.py", line 1823, in _run_once
    event_list = self._selector.select(timeout)
  File "/home/devengqc/miniconda3/lib/python3.8/selectors.py", line 468, in select
    fd_event_list = self._selector.poll(timeout, max_ev)
KeyboardInterrupt
Task was destroyed but it is pending!
task: <Task pending name='Task-8' coro=<NotebookClient._async_poll_for_reply() running at /home/devengqc/miniconda3/lib/python3.8/site-packages/nbclient/client.py:774> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x7f9215075250>()]> cb=[<TaskWakeupMethWrapper object at 0x7f9214b0e070>()]>
Task was destroyed but it is pending!
task: <Task pending name='Task-7' coro=<NotebookClient._async_poll_output_msg() running at /home/devengqc/miniconda3/lib/python3.8/site-packages/nbclient/client.py:806> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x7f9215075220>()]>>
Task was destroyed but it is pending!
task: <Task pending name='Task-6' coro=<NotebookClient._async_poll_kernel_alive() running at /home/devengqc/miniconda3/lib/python3.8/site-packages/nbclient/client.py:816> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x7f921508a3d0>()]>>

It looks from the stack trace like it’s stuck trying to run one of the cells in your notebook. Have you tried running it directly in jupyter?

Hello Jeremy,
It does finish its execution when I try the commands in jupyter.

However, I can’t run the make docs_serve command to see the built site locally as it still tries to run nbdev_build_docs which still does not work.

Making it run serially does not work either.
image

There are no tests or functions in the notebooks which would take a long time to execute. Here is a link to the git repo. deven-gqc/test_nbdev (github.com)

@jeremy sorry to bother you! I’m still unable to fix this issue, can you please help me fix this?

No I can’t reproduce it sorry

Is there anyway in notebooks to do a pause with the debugger and step around the stack trace?

Yes “pdb.set_trace”

I created a new environment with a different python version and that seems to have fixed the issue.
Earlier, I was using python 3.8.12, whereas in the new environment with python 3.7.13, nbdev works like a charm.

1 Like

I’m glad you found a fix – quite a mystery!