Cowboy production dependency

I am building and deploying a production build from a local development environment that matches the same OS as the production environment.

I am using Releases and environment variables in the releases.exs file. Before starting the server on production, I set the environment variables and they are read correctly.

However, I am getting an error when using Plug.Upload.

The error log shows 'ArgumentError unknown application: nil` and the error is for Cowboy and the path is local to the development environment instead of the production environment.

Why are local dependencies (cowboy specifically) being referenced in the error log? My mix.exs file does not have cowboy as a direct dependency and instead has plug_cowboy 2.0.

plug_cowboy (from v2.1.2…) pulls the following dependencies:

  def deps do
    [
      {:plug, "~> 1.7"},
      {:cowboy, "~> 2.5"},
      {:ex_doc, "~> 0.20", only: :docs},
      {:hackney, "~> 1.2.0", only: :test},
      {:kadabra, "0.3.4", only: :test},
      {:x509, "~> 0.6.0", only: :test}
    ]
  end

which explains the possibility of a cowboy related error.

Why it’s failing is another issue… we would need the contents of your config files to help (config.exs, dev.exs, prod.exs, releases.exs). Highlight the path that it’s returning in the error message and strip out any sensitive information that often sits in the config files.

1 Like

I’m making 2 assumptions which appear wrong, possibly?

Assumption 1 is releases.exs would read the get_env at app server startup rather than build time.

Assumption 2 is building/releasing in a development environment that matches production would compile dependencies in _build/prod that are specific for production and run fine. The cowboy error below refutes that since it remembers the /local/path/to/ my development environment.

error
** (exit) an exception was raised:
** (ArgumentError) unknown application: nil
(elixir 1.10.4) lib/application.ex:885: Application.app_dir/1
(plug 1.10.3) lib/plug/static.ex:393: Plug.Static.path/2
(plug 1.10.3) lib/plug/static.ex:176: Plug.Static.call/2

(cowboy 2.8.0) /home/{local-dev-user}/local/path/to/deps/cowboy/src/cowboy_stream_h.erl:300: :cowboy_stream_h.execute/3

releases.exs
key_a: System.get_env(“KEY_A_ENV”)

mix.exs
elixir: “~> 1.7”,

def application do
[
mod: {App.Application, []},
extra_applications: [:logger, :runtime_tools, :os_mon]
]

endpoint.ex
plug Plug.Static, at: “/some/path/here”, from: App.Get.Env.get_dynamic_path()

defmodule App.Get.Env
def get_dynamic_path() do
Application.get_env(:app, AppWeb.Endpoint)[:key_a]
end

Plug initialization happens at compile-time outside of MIX_ENV=dev if you haven’t changed any configuration for that. If the variables behind your Application.get_env call from App.Get.Env are intended to be defined at runtime and are not present in the normal config/*.exs files, you’ll see this behavior.

Please don’t immediately change the setting back to runtime initialization of Plugs without reading and understanding the caveats for performance - it’s much slower than a compiled release would ordinarily be.

3 Likes

Yes, that makes sense but for the 2nd issue, I’m confused why the cowboy error lists a dependency from my local development environment (example: /home/{local-dev-user}/local/path/to/deps/cowboy/src/). If there were an error, shouldn’t it be from _build/prod/* instead of my local /home/ folder?

Here’s a subset of my build commands, before I set environment variables.

mix deps.clean --all
mix deps.get --only prod
npm install --prefix ./assets
npm run deploy --prefix ./assets
mix phx.digest
MIX_ENV=prod mix release

Thats how debugging symbols in C related libraries work. No need to worry. Whatever builds the C sources, does build them in the deps folder rather than in the _build. This is not easy to fix from within mix and would require to be fixed in the build scripts of the dependencies that build their NIFs “inplace”.

2 Likes

What would be the correct way to dynamically set compile time parameters based on the environment being compiled for, to avoid a performance hit?