{"id":2829,"date":"2026-03-06T14:12:48","date_gmt":"2026-03-06T14:12:48","guid":{"rendered":"https:\/\/hauweele.net\/~gawen\/blog\/?p=2829"},"modified":"2026-03-06T14:17:31","modified_gmt":"2026-03-06T14:17:31","slug":"awscli-v2-34-3-on-freebsd-15-0-_awscrt-shenanigans","status":"publish","type":"post","link":"https:\/\/hauweele.net\/~gawen\/blog\/?p=2829","title":{"rendered":"awscli v2.34.3 on FreeBSD 15.0: _awscrt shenanigans"},"content":{"rendered":"<p>I had been running AWS CLI v2 on FreeBSD for a while, and it stopped working after I updated to the latest release. I checked out v2.34.3 from the awscli v2 repo, installed the dependencies from <code>requirements.txt<\/code>, making sure there were no conflicts with locally installed packages \u2014 in particular <code>awscrt<\/code>, where I used the latest available version as specified in the requirements. The <code>aws<\/code> command itself ran fine:<\/p>\n<pre>\u00bb aws --version\r\naws-cli\/2.34.3 Python\/3.11.14 FreeBSD\/15.0-RELEASE-p2 source\/amd64<\/pre>\n<p>But as soon as it needed to do anything real, it fell apart:<\/p>\n<pre>\u00bb aws configure sso\r\n\r\naws: [ERROR]: module '_awscrt' has no attribute 'set_log_level'<\/pre>\n<p>A bit of digging showed <code>awscrt\/io.py<\/code> calling <code>_awscrt.set_log_level(log_level)<\/code>.<\/p>\n<p>For some context, the <a href=\"https:\/\/pypi.org\/project\/awscrt\">awscrt<\/a> package is the AWS Common Runtime binding for Python, and it&#8217;s split into two parts. The pure Python layer lives in the <code>awscrt<\/code> package and handles the high-level API. The actual work is done by <code>_awscrt<\/code>, a C extension compiled as a library (a <code>.so<\/code> file) which on a typical FreeBSD + Python 3.11 setup would live at <code>\/usr\/local\/lib\/python3.11\/site-packages\/_awscrt.abi3.so<\/code>.<\/p>\n<p>I had manually installed <code>awscrt==0.31.2<\/code>, the latest release at the time of writing, and also exactly the version pinned in awscli&#8217;s <code>requirements.txt<\/code>. Still, the error persisted. The Python wrapper was clearly calling something the <code>.so<\/code> didn&#8217;t expose.<\/p>\n<p>The clue came from checking where Python was actually loading things from:<\/p>\n<pre>\u00bb python3 -c \"import awscrt; print(awscrt.__version__, awscrt.__file__)\"\r\n0.31.2 \/usr\/local\/lib\/python3.11\/site-packages\/awscrt\/__init__.py\r\n\u00bb python3 -c \"import _awscrt; print(_awscrt.__file__)\"\r\n\/home\/myuser\/.local\/lib\/python3.11\/site-packages\/_awscrt.abi3.so<\/pre>\n<p><i>There it is.<\/i> The Python part of <code>awscrt<\/code> was correctly loading from the system-wide site-packages. But <code>_awscrt<\/code>, the compiled extension, was being pulled from my user&#8217;s local site-packages. Probably a leftover from a previous install that I hadn&#8217;t properly cleaned up.<\/p>\n<p>After removing the dangling file from <code>~\/.local\/lib\/python3.11\/site-packages\/<\/code>, the check came back clean:<\/p>\n<pre>\u00bb python3 -c \"import _awscrt; print(_awscrt.__file__)\"\r\n\/usr\/local\/lib\/python3.11\/site-packages\/_awscrt.abi3.so<\/pre>\n<p>And with that, <code>aws configure sso<\/code> ran without complaint.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I had been running AWS CLI v2 on FreeBSD for a while, and it stopped working after I updated to the latest release. I checked out v2.34.3 from the awscli v2 repo, installed the dependencies from requirements.txt, making sure there &hellip; <a href=\"https:\/\/hauweele.net\/~gawen\/blog\/?p=2829\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[1210,1211,1173,389,120],"class_list":["post-2829","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-awscli","tag-awscrt","tag-dependency","tag-freebsd","tag-python"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/hauweele.net\/~gawen\/blog\/index.php?rest_route=\/wp\/v2\/posts\/2829","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hauweele.net\/~gawen\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hauweele.net\/~gawen\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hauweele.net\/~gawen\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/hauweele.net\/~gawen\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2829"}],"version-history":[{"count":0,"href":"https:\/\/hauweele.net\/~gawen\/blog\/index.php?rest_route=\/wp\/v2\/posts\/2829\/revisions"}],"wp:attachment":[{"href":"https:\/\/hauweele.net\/~gawen\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2829"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hauweele.net\/~gawen\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2829"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hauweele.net\/~gawen\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2829"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}