Phoenix exception when returning from error_view.ex

885 views
Skip to first unread message

Jordi Chacón

unread,
May 25, 2015, 3:34:34 AM5/25/15
to elixir-l...@googlegroups.com
Hi,

I am writing a Phoenix application which serves a json-api API.

My error_view.ex gets called whenever a 404 or a 500 occur. Under these error scenarios I want:
* the response body to be an empty json body %{}
* the content-type response header to be "application/vnd.api+json"

That is the behaviour I get right now. Cool. But even though the end result is what I want, Phoenix is throwing (and logging) an exception internally.


What am I doing wrong that causes this exception? How can I fix it?

Thank you for your help!

José Valim

unread,
May 25, 2015, 3:54:08 AM5/25/15
to elixir-l...@googlegroups.com
It is still an error. The error_view is called so you render something to the client, it doesn't change the fact that something went wrong and that it must be logged.



José Valim
Skype: jv.ptec
Founder and Lead Developer

--
You received this message because you are subscribed to the Google Groups "elixir-lang-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-ta...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-talk/495a2e83-cf8b-42ee-bbd7-ef473c374e46%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Jordi Chacón

unread,
May 25, 2015, 9:49:34 AM5/25/15
to elixir-l...@googlegroups.com, jose....@plataformatec.com.br
Thanks for your reply José.

The thing is, this exception didn't happen before when I was using "application/json" as "accept" request header.

Let me clarify:
This morning I changed my application so that it now requires "application/vnd.api+json" as "accept" request header instead of "application/json". As soon as I did the change, Phoenix started to throw this exception in 404 scenario. I have checked out the previous version to confirm this and it is the case, Phoenix did not throw any exception when handling a 404 using "application/json".

What have I changed to require "application/vnd.api+json"?

1. Added this to my config.exs
config :plug,
  :mimes, %{"application/vnd.api+json" => ["json-api"]}

2. In my endpoint.ex module, replaced `plug :accepts, ["json"]` with `plug :accepts, ["json-api"]`

3. In error_view.ex, replaced "400.json" with "400.json-api" (as it shows in the Gist I posted earlier)

4. In error_view.ex, the render/2 function used to return an empty map %{}, but this was crashing now (as in, causing a 500):

#PID<0.388.0> running FacebookService.Endpoint terminated
Server: localhost:4001 (http)
Request: GET /oops
** (exit) an exception was raised:
    ** (FunctionClauseError) no function clause matching in Plug.Conn.resp/3
        (plug) lib/plug/conn.ex:434: Plug.Conn.resp(%Plug.Conn{adapter: {Plug.Adapters.Cowboy.Conn, :...}, assigns: %{correlation_id: "1234", correlation_id_presence_failed?: false, kind: :error, layout: false, reason: %Phoenix.Router.NoRouteError{conn: %Plug.Conn{adapter: {Plug.Adapters.Cowboy.Conn, :...}, assigns: %{correlation_id: "1234", correlation_id_presence_failed?: false, request_reception_timestamp: {1432, 561479, 57438}}, before_send: [#Function<0.101105578/1 in HTTPex.Plugs.HTTPLogger.call/2>], body_params: %{}, cookies: %Plug.Conn.Unfetched{aspect: :cookies}, halted: false, host: "localhost", method: "GET", owner: #PID<0.388.0>, params: %{"format" => "json-api"}, path_info: ["oops"], peer: {{127, 0, 0, 1}, 56063}, port: 4001, private: %{phoenix_endpoint: FacebookService.Endpoint, phoenix_pipelines: [], phoenix_router: FacebookService.Router}, query_params: %{}, query_string: "", remote_ip: {127, 0, 0, 1}, req_cookies: %Plug.Conn.Unfetched{aspect: :cookies}, req_headers: [{"accept", "application/vnd.api+json"}, {"shim-correlation-id", "1234"}, {"user-agent", "hackney/1.1.0"}, {"host", "localhost:4001"}], resp_body: nil, resp_cookies: %{}, resp_headers: [{"cache-control", "max-age=0, private, must-revalidate"}], scheme: :http, script_name: [], secret_key_base: "mcV+tU17meac6XZ+cvGLaV5+By4XXr24wR87fTTUVLy/G6w+E4umFDLYe72cBA5J", state: :unset, status: nil}, message: "no route found for GET /oops (FacebookService.Router)", plug_status: 404, router: FacebookService.Router}, request_reception_timestamp: {1432, 561479, 57438}, stack: [{FacebookService.Router, :match, 4, [file: 'web/router.ex', line: 1]}, {FacebookService.Router, :call, 2, [file: 'lib/phoenix/router.ex', line: 2]}, {FacebookService.Endpoint, :phoenix_endpoint_pipeline, 1, [file: 'lib/facebook_service/endpoint.ex', line: 1]}, {FacebookService.Endpoint, :call, 2, [file: 'lib/phoenix/endpoint/render_errors.ex', line: 34]}, {Phoenix.Endpoint.CowboyHandler, :upgrade, 4, [file: 'lib/phoenix/endpoint/cowboy_handler.ex', line: 52]}, {:cowboy_protocol, :execute, 4, [file: 'src/cowboy_protocol.erl', line: 435]}]}, before_send: [#Function<0.101105578/1 in HTTPex.Plugs.HTTPLogger.call/2>], body_params: %{}, cookies: %Plug.Conn.Unfetched{aspect: :cookies}, halted: false, host: "localhost", method: "GET", owner: #PID<0.388.0>, params: %{"format" => "json-api"}, path_info: ["oops"], peer: {{127, 0, 0, 1}, 56063}, port: 4001, private: %{phoenix_endpoint: FacebookService.Endpoint, phoenix_layout: false, phoenix_pipelines: [], phoenix_router: FacebookService.Router, phoenix_template: "404.json-api", phoenix_view: FacebookService.ErrorView}, query_params: %{}, query_string: "", remote_ip: {127, 0, 0, 1}, req_cookies: %Plug.Conn.Unfetched{aspect: :cookies}, req_headers: [{"accept", "application/vnd.api+json"}, {"shim-correlation-id", "1234"}, {"user-agent", "hackney/1.1.0"}, {"host", "localhost:4001"}], resp_body: nil, resp_cookies: %{}, resp_headers: [{"content-type", "application/vnd.api+json; charset=utf-8"}, {"cache-control", "max-age=0, private, must-revalidate"}], scheme: :http, script_name: [], secret_key_base: "mcV+tU17meac6XZ+cvGLaV5+By4XXr24wR87fTTUVLy/G6w+E4umFDLYe72cBA5J", state: :unset, status: 404}, 404, %{})
        (plug) lib/plug/conn.ex:424: Plug.Conn.send_resp/3
        (phoenix) lib/phoenix/endpoint/cowboy_handler.ex:52: Phoenix.Endpoint.CowboyHandler.upgrade/4
        (cowboy) src/cowboy_protocol.erl:435: :cowboy_protocol.execute/4, now it returns a conn (

Why does this crash after I changed from "application/json" to "application/vnd.api+json"? This is really my question.

Anyway, user voltone from #elixir-lang suggested I call Phoenix.Controller.json(%{})) instead of returning %{}. That helped with returning the 404, but Phoenix still threw an exception.

José Valim

unread,
May 25, 2015, 9:56:30 AM5/25/15
to elixir-l...@googlegroups.com
Ah, I see. That's because you also need to tell Phoenix how to encode json-api:

      config :phoenix, :format_encoders, "json-api": Poison

Than the previous code should work too.

Also remember to take those discussions to Phoenix mailing list. :) It is more likely you will get a faster answer there.



José Valim
Skype: jv.ptec
Founder and Lead Developer

Jordi Chacón

unread,
May 28, 2015, 1:36:55 AM5/28/15
to elixir-l...@googlegroups.com, jose....@plataformatec.com.br
Great! That made the exception disappear. Thank you very much José!
Reply all
Reply to author
Forward
0 new messages