Debugging an issue with Pelican
This site is built entirely with the Pelican static site generator. The other day I noticed that site builds were failing and I wasn't sure why.
ERROR Skipping /home/janis/PelicanSite/content/blog/printers_manufacturing.md: could not find information about 'title' log.py:96
ERROR Skipping /home/janis/PelicanSite/content/IT_industry/automation_and_RPA/telephony.md: could not find information about 'title' log.py:96
[19:47:51] CRITICAL ValueError: invalid literal for int() with base 10: '' __init__.py:566
This error message is particularly annoying since it basically tells you nothing.
What I did to debug this is go modify the Pelican code that is installed in site-packages directly.
Looking at the pelican source code we see the following in __init__.py
:
def main(argv=None):
args = parse_arguments(argv)
logs_dedup_min_level = getattr(logging, args.logs_dedup_min_level)
init_logging(level=args.verbosity, fatal=args.fatal,
name=__name__, logs_dedup_min_level=logs_dedup_min_level)
logger.debug('Pelican version: %s', __version__)
logger.debug('Python version: %s', sys.version.split()[0])
try:
pelican, settings = get_instance(args)
if args.autoreload and args.listen:
excqueue = multiprocessing.Queue()
p1 = multiprocessing.Process(
target=autoreload,
args=(args, excqueue))
p2 = multiprocessing.Process(
target=listen,
args=(settings.get('BIND'), settings.get('PORT'),
settings.get("OUTPUT_PATH"), excqueue))
p1.start()
p2.start()
exc = excqueue.get()
p1.terminate()
p2.terminate()
if exc is not None:
logger.critical(exc)
elif args.autoreload:
autoreload(args)
elif args.listen:
listen(settings.get('BIND'), settings.get('PORT'),
settings.get("OUTPUT_PATH"))
else:
watcher = FileSystemWatcher(args.settings, Readers, settings)
watcher.check()
with console.status("Generating..."):
pelican.run()
except KeyboardInterrupt:
logger.warning('Keyboard interrupt received. Exiting.')
except Exception as e:
logger.critical("%s: %s", e.__class__.__name__, e) # this is __init.py__ line 566
if args.verbosity == logging.DEBUG:
console.print_exception()
sys.exit(getattr(e, 'exitcode', 1))
What I really wanted to see is the stacktrace here, so I changed the exception here to always be printed because the call to Pelican happens in a script and I didn't want to change that script just to debug.
This then gave the following:
CRITICAL ValueError: invalid literal for int() with base 10: '' __init__.py:566
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ │
│ /home/janis/PelicanSite/venv/lib/python3.7/site-packages/pelican/__init__.py:562 in main │
│ │
│ 559 │ │ │ watcher = FileSystemWatcher(args.settings, Readers, settings) │
│ 560 │ │ │ watcher.check() │
│ 561 │ │ │ with console.status("Generating..."): │
│ ❱ 562 │ │ │ │ pelican.run() │
│ 563 │ except KeyboardInterrupt: │
│ 564 │ │ logger.warning('Keyboard interrupt received. Exiting.') │
│ 565 │ except Exception as e: │
│ /home/janis/PelicanSite/venv/lib/python3.7/site-packages/pelican/__init__.py:115 in run │
│ │
│ 112 │ │ │
│ 113 │ │ for p in generators: │
│ 114 │ │ │ if hasattr(p, 'generate_context'): │
│ ❱ 115 │ │ │ │ p.generate_context() │
│ 116 │ │ │
│ 117 │ │ for p in generators: │
│ 118 │ │ │ if hasattr(p, 'refresh_metadata_intersite_links'): │
│ │
│ /home/janis/PelicanSite/venv/lib/python3.7/site-packages/pelican/generators.py:699 in │
│ generate_context │
│ │
│ 696 │ │ │ 'authors', 'related_posts')) │
│ 697 │ │ self.save_cache() │
│ 698 │ │ self.readers.save_cache() │
│ ❱ 699 │ │ signals.article_generator_finalized.send(self) │
│ 700 │ │
│ 701 │ def generate_output(self, writer): │
│ 702 │ │ self.generate_feeds(writer) │
│ │
│ /home/janis/PelicanSite/venv/lib/python3.7/site-packages/blinker/base.py:267 in send │
│ │
│ 264 │ │ │ return [] │
│ 265 │ │ else: │
│ 266 │ │ │ return [(receiver, receiver(sender, **kwargs)) │
│ ❱ 267 │ │ │ │ │ for receiver in self.receivers_for(sender)] │
│ 268 │ │
│ 269 │ def has_receivers_for(self, sender): │
│ 270 │ │ """True if there is probably a receiver for *sender*. │
│ │
│ /home/janis/PelicanSite/venv/lib/python3.7/site-packages/blinker/base.py:267 in <listcomp> │
│ │
│ 264 │ │ │ return [] │
│ 265 │ │ else: │
│ 266 │ │ │ return [(receiver, receiver(sender, **kwargs)) │
│ ❱ 267 │ │ │ │ │ for receiver in self.receivers_for(sender)] │
│ 268 │ │
│ 269 │ def has_receivers_for(self, sender): │
│ 270 │ │ """True if there is probably a receiver for *sender*. │
│ │
│ /home/janis/PelicanSite/pelican-plugins/series/series.py:45 in aggregate_series │
│ │
│ 42 │ │ date_order_articles = [ │
│ 43 │ │ │ art_tup for art_tup in series_articles if art_tup[0] is None] │
│ 44 │ │ │
│ ❱ 45 │ │ forced_order_articles.sort(key=integer_index_sort) │
│ 46 │ │ date_order_articles.sort(key=itemgetter(1)) │
│ 47 │ │ │
│ 48 │ │ all_articles = forced_order_articles + date_order_articles │
│ │
│ /home/janis/PelicanSite/pelican-plugins/series/series.py:16 in integer_index_sort │
│ │
│ 13 from pelican import signals │
│ 14 │
│ 15 def integer_index_sort(items): │
│ ❱ 16 │ return int(items[0]) │
│ 17 │
│ 18 def aggregate_series(generator): │
│ 19 │ series = defaultdict(list) │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
ValueError: invalid literal for int() with base 10: ''
make: *** [Makefile:49: html] Error 1
This is entirely more useful and we now see that the issue is something to do with the sequence numbers for a series. This isn't the first time I've run into an issue with series.
This issue arose because I had a draft post with the following metadata section:
---
Title: Problems with Celsius
Authors: Janis Lesinskis
Date: 2021-11-25
Category: Economics
Tags: economics, cryptocurrencies, banking, currencies, forex
Slug: problems-with-celsius
Summary: The Celsius product was something that always annoyed me, in part because I'd only ever hear about it from rabid shills. And also because taking leverage on cryptocurrencies is not something I think is wise at all.
Series: MonetaryPolicy
series_index:
---
Note the missing series_index
here. Also notice the missing Status: draft
as well. The fix here was rather easy, just add a draft tag. But as a library designer I might raise a slightly more descriptive error message in a situation like this.
I think this is a good reminder that there's times that digging into the site-packages is a good way to debug issues in libraries you are using.