dbt-core: DBT cli throw memory exception for ffi.callback() on Mac with Apple Sillicon

Describe the bug

dbt run or dbt --version throw error Cannot allocate write+execute memory for ffi.callback().

Steps To Reproduce

On Macbook pro with M1 chip brew tap fishtown-analytics/dbt brew install dbt add default profile.yml with connection to snowflake create new project dbt init dbt run with the two sample models, or simply dbt --version

Expected behavior

Should complete successfully, instead of throwing exception. The process works fine on Intel-based Macbook pro.

Screenshots and log output

> dbt run
Running with dbt=0.19.0
Found 3 models, 8 tests, 0 snapshots, 0 analyses, 143 macros, 0 operations, 0 seed files, 0 sources, 0 exposures
Encountered an error:
Cannot allocate write+execute memory for ffi.callback(). You might be running on a system that prevents this. For more information, see https://cffi.readthedocs.io/en/latest/using.html#callbacks

System information

Which database are you using dbt with?

  • postgres
  • redshift
  • bigquery
  • snowflake
  • other (specify: ____________)

The output of dbt --version:

Encountered an error:
Cannot allocate write+execute memory for ffi.callback(). You might be running on a system that prevents this. For more information, see https://cffi.readthedocs.io/en/latest/using.html#callbacks

The operating system you’re using: macOS Big Sur 11.2.2

The output of python --version: 3.8.7

Additional context

Add any other context about the problem here.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 5
  • Comments: 24 (9 by maintainers)

Most upvoted comments

TL;DR: if you experience the error during dbt run, just add those lines to ~/.dbt/profiles.yml (see the full doc in profiles.yml here)

config:
    send_anonymous_usage_stats: False

Details:

Here’s the stack trace (MacBook Air (M1, 2020) running Mac OS 11.3.1). The exception is raised in user behavior tracking code. Quickfix will be disabling tracking (see above). I guess the proper way to handle this would be wrapping tracker.flush() with try/except. Failure to track isn’t a critical error after all

Traceback (most recent call last):
  File "/opt/homebrew/Cellar/dbt/0.19.1_1/libexec/lib/python3.8/site-packages/dbt/main.py", line 125, in main
    results, succeeded = handle_and_check(args)
  File "/opt/homebrew/Cellar/dbt/0.19.1_1/libexec/lib/python3.8/site-packages/dbt/main.py", line 203, in handle_and_check
    task, res = run_from_args(parsed)
  File "/opt/homebrew/Cellar/dbt/0.19.1_1/libexec/lib/python3.8/site-packages/dbt/main.py", line 256, in run_from_args
    results = task.run()
  File "/opt/homebrew/Cellar/python@3.8/3.8.10/Frameworks/Python.framework/Versions/3.8/lib/python3.8/contextlib.py", line 131, in __exit__
    self.gen.throw(type, value, traceback)
  File "/opt/homebrew/Cellar/dbt/0.19.1_1/libexec/lib/python3.8/site-packages/dbt/main.py", line 229, in track_run
    dbt.tracking.flush()
  File "/opt/homebrew/Cellar/dbt/0.19.1_1/libexec/lib/python3.8/site-packages/dbt/tracking.py", line 428, in flush
    tracker.flush()
  File "/opt/homebrew/Cellar/dbt/0.19.1_1/libexec/lib/python3.8/site-packages/snowplow_tracker/tracker.py", line 218, in flush
    emitter.sync_flush()
  File "/opt/homebrew/Cellar/dbt/0.19.1_1/libexec/lib/python3.8/site-packages/snowplow_tracker/emitters.py", line 182, in sync_flush
    Emitter.flush(self)
  File "/opt/homebrew/Cellar/dbt/0.19.1_1/libexec/lib/python3.8/site-packages/snowplow_tracker/emitters.py", line 149, in flush
    self.send_events(self.buffer)
  File "/opt/homebrew/Cellar/dbt/0.19.1_1/libexec/lib/python3.8/site-packages/snowplow_tracker/emitters.py", line 206, in send_events
    status_code = self.http_post(data).status_code
  File "/opt/homebrew/Cellar/dbt/0.19.1_1/libexec/lib/python3.8/site-packages/dbt/tracking.py", line 68, in http_post
    r = requests.post(
  File "/opt/homebrew/Cellar/dbt/0.19.1_1/libexec/lib/python3.8/site-packages/requests/api.py", line 119, in post
    return request('post', url, data=data, json=json, **kwargs)
  File "/opt/homebrew/Cellar/dbt/0.19.1_1/libexec/lib/python3.8/site-packages/requests/api.py", line 61, in request
    return session.request(method=method, url=url, **kwargs)
  File "/opt/homebrew/Cellar/dbt/0.19.1_1/libexec/lib/python3.8/site-packages/requests/sessions.py", line 530, in request
    resp = self.send(prep, **send_kwargs)
  File "/opt/homebrew/Cellar/dbt/0.19.1_1/libexec/lib/python3.8/site-packages/requests/sessions.py", line 643, in send
    r = adapter.send(request, **kwargs)
  File "/opt/homebrew/Cellar/dbt/0.19.1_1/libexec/lib/python3.8/site-packages/requests/adapters.py", line 439, in send
    resp = conn.urlopen(
  File "/opt/homebrew/Cellar/dbt/0.19.1_1/libexec/lib/python3.8/site-packages/urllib3/connectionpool.py", line 670, in urlopen
    httplib_response = self._make_request(
  File "/opt/homebrew/Cellar/dbt/0.19.1_1/libexec/lib/python3.8/site-packages/urllib3/connectionpool.py", line 381, in _make_request
    self._validate_conn(conn)
  File "/opt/homebrew/Cellar/dbt/0.19.1_1/libexec/lib/python3.8/site-packages/urllib3/connectionpool.py", line 978, in _validate_conn
    conn.connect()
  File "/opt/homebrew/Cellar/dbt/0.19.1_1/libexec/lib/python3.8/site-packages/urllib3/connection.py", line 343, in connect
    self.ssl_context = create_urllib3_context(
  File "/opt/homebrew/Cellar/dbt/0.19.1_1/libexec/lib/python3.8/site-packages/urllib3/util/ssl_.py", line 290, in create_urllib3_context
    context.verify_mode = cert_reqs
  File "/opt/homebrew/Cellar/dbt/0.19.1_1/libexec/lib/python3.8/site-packages/urllib3/contrib/pyopenssl.py", line 438, in verify_mode
    self._ctx.set_verify(_stdlib_to_openssl_verify[value], _verify_callback)
  File "/opt/homebrew/Cellar/dbt/0.19.1_1/libexec/lib/python3.8/site-packages/OpenSSL/SSL.py", line 1028, in set_verify
    self._verify_helper = _VerifyHelper(callback)
  File "/opt/homebrew/Cellar/dbt/0.19.1_1/libexec/lib/python3.8/site-packages/OpenSSL/SSL.py", line 331, in __init__
    self.callback = _ffi.callback(
MemoryError: Cannot allocate write+execute memory for ffi.callback(). You might be running on a system that prevents this. For more information, see https://cffi.readthedocs.io/en/latest/using.html#callbacks

Hey @alyiwang, I was having similar issues and I was able to work through it using the following:

  • First, follow this link to alter your terminal of choice (I was using iterm) to https://alexslobodnik.medium.com/apple-m1-python-pandas-and-homebrew-20f14828ccc7 open using Rosetta
  • Uninstall all versions of dbt through brew uninstall dbt if you already tried installing
  • I performed the above until which dbt returned nothing (at this point I had multiple installs of dbt that I had to get rid of
  • Once my system was rid of dbt, I shifted over to the python virtual environment route. Using Python 3.8, I ran pip install virtualenv and created a virtual environment. Link for more info on those https://packaging.python.org/guides/installing-using-pip-and-virtual-environments/
  • After activating the environment I ran pip install dbt==0.18.0 and let it run it’s course. Following installation I ran dbt --version while the environment was still active and it worked. It’s worth noting that if you go this route of installation, the virtual environment must first be activated before running any dbt commands and deactivated when complete

To make the installation work, a couple changes will need to be made from dbt to:

  1. allow python3.9
  2. use latest version 2.4.1 of snowflake-connector-python @jtcohen6 do you think this can be put into the roadmap or feature request of DBT?

@alyiwang This is absolutely our plan for the next minor version of dbt (v0.20.0). dbt-core already supports python3.9, it’s just a matter of upgrading our pin on the Snowflake connector.

@tpark464 I would recommend using the latest version of dbt and the associated adapter (brew install dbt-redshift). We are on v1.2 at the moment. The older versions of dbt in Homebrew are not actively maintained and have breaking dependency changes over the long time period

@brittianwarner We didn’t include the proposed fix above in v0.20.0. You’re welcome to try turning off anonymous tracking, and see if that fixes it.

Over the past few weeks, there have been a few reports of successful installs on M1s by other means: https://github.com/dbt-labs/dbt/issues/3239#issuecomment-868996761

@vklimontovich Have you been able to confirm that the addition of that try/except results in error-free runs? (i.e. by cloning dbt, editing, and installing from local)

That’s fine as a temporary solution—if you can confirm it works, I’d welcome a PR for it. In addition, I’d like to find a way to work around the pyOpenSSL bug, if possible.

We’ve just run headfirst into this issue with a colleague using a new macbook 😂 ; any rough timelines for a v0.20.0 pre-release @jtcohen6?

Just ran into the issue as well today on my new work computer. If there is anything I can do to help out I’d be happy to chip in. The snowflake-python-connector continues to be my biggest pain in the behind with their dependency management.