Getting runtime error

I have an old app
when I tried to run it (after compile) I am getting this runtime error

attempting to set id attribute to 0, but setting the DOM ID to a number can lead to unpredictable behaviour. Instead consider prefixing the id with a string, such as "user-0" or similar

the problem is inside the “lib/phoenix_html.ex” at line 285

can u help?

Did you try doing what the error message asks you to do and change the ID of the DOM node to something other than a number?

This is exactly what I don’t know what ID is all about
I did not defined it.
The error is in a ex file that is part of the Phoenix framework

I wish I knew what is this id

You should show the full stack trace and the code files that are listed in the stack trace. Even if the error is reported by Phoenix, it may be in your code (that calls Phoenix).

# ArgumentError at GET /

Exception:

    ** (ArgumentError) attempting to set id attribute to 0, but setting the DOM ID to a number can lead to unpredictable behaviour. Instead consider prefixing the id with a string, such as "user-0" or similar
        (phoenix_html 3.3.3) lib/phoenix_html.ex:285: Phoenix.HTML.id_value/1
        (phoenix_html 3.3.3) lib/phoenix_html.ex:235: Phoenix.HTML.build_attrs/1
        (phoenix_html 3.3.3) lib/phoenix_html.ex:265: Phoenix.HTML.build_attrs/1
        (phoenix_html 3.3.3) lib/phoenix_html.ex:218: Phoenix.HTML.attributes_escape/1
        (phoenix_live_view 0.17.14) lib/phoenix_live_view/helpers.ex:1145: anonymous fn/2 in Phoenix.LiveView.Helpers.form/1
        (phoenix_live_view 0.17.14) lib/phoenix_live_view/diff.ex:387: Phoenix.LiveView.Diff.traverse/7
        (phoenix_live_view 0.17.14) lib/phoenix_live_view/diff.ex:494: anonymous fn/4 in Phoenix.LiveView.Diff.traverse_dynamic/7
        (elixir 1.15.7) lib/enum.ex:2510: Enum."-reduce/3-lists^foldl/2-0-"/3
        (phoenix_live_view 0.17.14) lib/phoenix_live_view/diff.ex:387: Phoenix.LiveView.Diff.traverse/7
        (phoenix_live_view 0.17.14) lib/phoenix_live_view/diff.ex:664: Phoenix.LiveView.Diff.render_component/9
        (phoenix_live_view 0.17.14) lib/phoenix_live_view/diff.ex:609: anonymous fn/5 in Phoenix.LiveView.Diff.render_pending_components/6
        (elixir 1.15.7) lib/enum.ex:2510: Enum."-reduce/3-lists^foldl/2-0-"/3
        (stdlib 5.1.1) maps.erl:416: :maps.fold_1/4
        (phoenix_live_view 0.17.14) lib/phoenix_live_view/diff.ex:582: Phoenix.LiveView.Diff.render_pending_components/6
        (phoenix_live_view 0.17.14) lib/phoenix_live_view/diff.ex:145: Phoenix.LiveView.Diff.render/3
        (phoenix_live_view 0.17.14) lib/phoenix_live_view/static.ex:244: Phoenix.LiveView.Static.to_rendered_content_tag/4
        (phoenix_live_view 0.17.14) lib/phoenix_live_view/static.ex:126: Phoenix.LiveView.Static.render/3
        (phoenix_live_view 0.17.14) lib/phoenix_live_view/controller.ex:39: Phoenix.LiveView.Controller.live_render/3
        (phoenix 1.6.16) lib/phoenix/router.ex:354: Phoenix.Router.__call__/2
        (jot 0.1.0) lib/jot_web/endpoint.ex:1: JotWeb.Endpoint.plug_builder_call/2
    

Code:

`lib/phoenix_html.ex`

    280   
    281     defp nested_attrs([], _attr, t),
    282       do: build_attrs(t)
    283   
    284     defp id_value(value) when is_number(value) do
    285>      raise ArgumentError,
    286             "attempting to set id attribute to #{value}, " <>
    287               "but setting the DOM ID to a number can lead to unpredictable behaviour. " <>
    288               "Instead consider prefixing the id with a string, such as \"user-#{value}\" or similar"
    289     end
    290   
    
`lib/phoenix_html.ex`

    230   
    231     defp build_attrs([{_, nil} | t]),
    232       do: build_attrs(t)
    233   
    234     defp build_attrs([{:id, v} | t]),
    235>      do: [" id=\"", id_value(v), ?" | build_attrs(t)]
    236   
    237     defp build_attrs([{:class, v} | t]),
    238       do: [" class=\"", class_value(v), ?" | build_attrs(t)]
    239   
    240     defp build_attrs([{:aria, v} | t]) when is_list(v),
    
`lib/phoenix_html.ex`

    260   
    261     defp build_attrs([{"phx", v} | t]) when is_list(v),
    262       do: nested_attrs(v, " phx", t)
    263   
    264     defp build_attrs([{k, v} | t]),
    265>      do: [?\s, key_escape(k), ?=, ?", attr_escape(v), ?" | build_attrs(t)]
    266   
    267     defp build_attrs([]), do: []
    268   
    269     defp nested_attrs([{k, true} | kv], attr, t),
    270       do: [attr, ?-, key_escape(k) | nested_attrs(kv, attr, t)]
    
`lib/phoenix_html.ex`

    213         iex> safe_to_string attributes_escape(%{phx: [value: [foo: "bar"]]})
    214         " phx-value-foo=\"bar\""
    215   
    216     """
    217     def attributes_escape(attrs) when is_list(attrs) do
    218>      {:safe, build_attrs(attrs)}
    219     end
    220   
    221     def attributes_escape(attrs) do
    222       {:safe, attrs |> Enum.to_list() |> build_attrs()}
    223     end
    
`lib/phoenix_live_view/helpers.ex`

    1140           hidden_method: hidden_method,
    1141           attrs: attrs
    1142         )
    1143   
    1144       ~H"""
    1145>      <form {@attrs}>
    1146         <%= if @hidden_method && @hidden_method not in ~w(get post) do %>
    1147           <input name="_method" type="hidden" value={@hidden_method}>
    1148         <% end %>
    1149         <%= if @csrf_token do %>
    1150           <input name="_csrf_token" type="hidden" value={@csrf_token}>
    
`lib/phoenix_live_view/diff.ex`

    382            components,
    383            template,
    384            changed?
    385          ) do
    386       {_counter, diff, children, pending, components, template} =
    387>        traverse_dynamic(socket, dynamic.(false), %{}, pending, components, template, changed?)
    388   
    389       {diff, template} = maybe_template_static(diff, fingerprint, static, template)
    390       {diff, {fingerprint, children}, pending, components, template}
    391     end
    392   
    
`lib/phoenix_live_view/diff.ex`

    489       Enum.reduce(dynamic, {0, %{}, children, pending, components, template}, fn
    490         entry, {counter, diff, children, pending, components, template} ->
    491           child = Map.get(children, counter)
    492   
    493           {serialized, child_fingerprint, pending, components, template} =
    494>            traverse(socket, entry, child, pending, components, template, changed?)
    495   
    496           # If serialized is nil, it means no changes.
    497           # If it is an empty map, then it means it is a rendered struct
    498           # that did not change, so we don't have to emit it either.
    499           diff =
    
`lib/enum.ex`

    No code available.

`lib/phoenix_live_view/diff.ex`

    382            components,
    383            template,
    384            changed?
    385          ) do
    386       {_counter, diff, children, pending, components, template} =
    387>        traverse_dynamic(socket, dynamic.(false), %{}, pending, components, template, changed?)
    388   
    389       {diff, template} = maybe_template_static(diff, fingerprint, static, template)
    390       {diff, {fingerprint, children}, pending, components, template}
    391     end
    392   
    
`lib/phoenix_live_view/diff.ex`

    659   
    660           {changed?, linked_cid, prints} =
    661             maybe_reuse_static(rendered, socket, component, cids, components)
    662   
    663           {diff, component_prints, pending, components, nil} =
    664>            traverse(socket, rendered, prints, pending, components, nil, changed?)
    665   
    666           diff = if linked_cid, do: Map.put(diff, @static, linked_cid), else: diff
    667           {%{socket | fingerprints: component_prints}, pending, diff, components}
    668         else
    669           {socket, pending, %{}, components}
    
`lib/phoenix_live_view/diff.ex`

    604               end
    605   
    606             triplet =
    607               socket
    608               |> Utils.maybe_call_update!(component, new_assigns)
    609>              |> render_component(component, id, cid, new?, pending, cids, diffs, components)
    610   
    611             {triplet, Map.put(seen_ids, [component | id], true)}
    612           end)
    613         end)
    614   
    
`lib/enum.ex`

    No code available.

`maps.erl`

    No code available.

`lib/phoenix_live_view/diff.ex`

    577   
    578     defp render_pending_components(socket, pending, seen_ids, cids, diffs, components) do
    579       acc = {{%{}, diffs, components}, seen_ids}
    580   
    581       {{pending, diffs, components}, seen_ids} =
    582>        Enum.reduce(pending, acc, fn {component, entries}, acc ->
    583           entries = maybe_preload_components(component, Enum.reverse(entries))
    584   
    585           Enum.reduce(entries, acc, fn {cid, id, new?, new_assigns}, {triplet, seen_ids} ->
    586             {pending, diffs, components} = triplet
    587   
    
`lib/phoenix_live_view/diff.ex`

    140       # cid_to_component is used by maybe_reuse_static and it must be a copy before changes.
    141       # However, given traverse does not change cid_to_component, we can read it now.
    142       {cid_to_component, _, _} = components
    143   
    144       {cdiffs, components} =
    145>        render_pending_components(socket, pending, cid_to_component, %{}, components)
    146   
    147       socket = %{socket | fingerprints: prints}
    148       diff = maybe_put_title(diff, socket)
    149       {diff, cdiffs} = extract_events({diff, cdiffs})
    150   
    
`lib/phoenix_live_view/static.ex`

    239       Phoenix.HTML.Tag.content_tag(tag, "", attrs)
    240     end
    241   
    242     defp to_rendered_content_tag(socket, tag, view, attrs) do
    243       rendered = Utils.to_rendered(socket, view)
    244>      {_, diff, _} = Diff.render(socket, rendered, Diff.new_components())
    245       Phoenix.HTML.Tag.content_tag(tag, {:safe, Diff.to_iodata(diff)}, attrs)
    246     end
    247   
    248     defp load_live!(view_or_component, kind) do
    249       case view_or_component.__live__() do
    
`lib/phoenix_live_view/static.ex`

    121             {:data, data_attrs}
    122             | extended_attrs
    123           ]
    124   
    125           try do
    126>            {:ok, to_rendered_content_tag(socket, tag, view, attrs), socket.assigns}
    127           catch
    128             :throw, {:phoenix, :child_redirect, redirected, flash} ->
    129               {:stop, Utils.replace_flash(%{socket | redirected: redirected}, flash)}
    130           end
    131   
    
`lib/phoenix_live_view/controller.ex`

    34           end
    35         end
    36   
    37     """
    38     def live_render(%Plug.Conn{} = conn, view, opts \\ []) do
    39>      case LiveView.Static.render(conn, view, opts) do
    40         {:ok, content, socket_assigns} ->
    41           conn
    42           |> Phoenix.Controller.put_view(LiveView.Static)
    43           |> Phoenix.Controller.render(
    44             "template.html",
    
`lib/phoenix/router.ex`

    349           metadata = %{metadata | conn: halted_conn}
    350           :telemetry.execute([:phoenix, :router_dispatch, :stop], measurements, metadata)
    351           halted_conn
    352         %Plug.Conn{} = piped_conn ->
    353           try do
    354>            plug.call(piped_conn, plug.init(opts))
    355           else
    356             conn ->
    357               measurements = %{duration: System.monotonic_time() - start}
    358               metadata = %{metadata | conn: conn}
    359               :telemetry.execute([:phoenix, :router_dispatch, :stop], measurements, metadata)
    
`lib/jot_web/endpoint.ex`

    1>  defmodule JotWeb.Endpoint do
    2     use Phoenix.Endpoint, otp_app: :jot
    3   
    4     # The session will be stored in the cookie and signed,
    5     # this means its contents can be read but not tampered with.
    6     # Set :encryption_salt if you would also like to encrypt it.
    

## Connection details

### Params

    %{}

### Request info

  * URI: http://localhost:4000/
  * Query string: 

### Headers
  
  * accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
  * accept-encoding: gzip, deflate, br
  * accept-language: en-US,en;q=0.5
  * connection: keep-alive
  * cookie: CURR_USER={"Zehut":"056108053","Role":"teacher","LastName":"אלי","FirstName":"חיון","HashedPassword":"$2b$12$lZkVwlJHhFdchRw/z2buweDFKvhw4GN7SXHJSnT9x/kGbHcbHzTtW","IsAdmin":true}; _scandoc_key=SFMyNTY.g3QAAAADbQAAAAtfY3NyZl90b2tlbm0AAAAYT1hQRmZjZGJhMjVMSnV0VW0tYXdhZUdHbQAAAA1hY2FkZW1pY195ZWFybQAAAAjXqtep16TXk20AAAAKdXNlcl90b2tlbm0AAAAgcoBHTi4yaUX0RufK1wZC9N_VvjrUceeRwS1A52UAIoA.C3VLmvafTWYeirQgwgePNHj5v4Zgs-P5PIZ1jE2yIIU; user_remember_me=SFMyNTY.g2gDbQAAACA3kyrqsdXKl_XmwyTj55qcxQFzPiqgkNqrymBgt3qvcW4GAIeB61uLAWIATxoA.mTROo7ufEegj08Beuxr7w83CjXQX57LwDEZSFIf6_-o; _jot_key=SFMyNTY.g3QAAAADbQAAAAtfY3NyZl90b2tlbm0AAAAYem9SRjE0STBpaHhjSl9OTlFDQlBhY0ZYbQAAAA5saXZlX3NvY2tldF9pZG0AAAA7dXNlcnNfc2Vzc2lvbnM6RWVnXzI3X0loZGlldU9lTFBjVXBSaWpMdTVWMk1udm9VWUUtQV94VzFvZz1tAAAACnVzZXJfdG9rZW5tAAAAIBHoP9u_yIXYnrjniz3FKUYoy7uVdjJ76FGBPgP8VtaI.pgGxDmSGaHcGwCYrneHdWR0NxjRz3gGu2xe5s1x73aU; _jot_web_user_remember_me=SFMyNTY.g2gDbQAAACAR6D_bv8iF2J6454s9xSlGKMu7lXYye-hRgT4D_FbWiG4GADfE3l-LAWIATxoA.cakKHVYWiBmvtOXNa-n_dL8hb0zCfyGs2bk8i-hiZ60
  * dnt: 1
  * host: localhost:4000
  * sec-fetch-dest: document
  * sec-fetch-mode: navigate
  * sec-fetch-site: none
  * sec-fetch-user: ?1
  * upgrade-insecure-requests: 1
  * user-agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/118.0

### Session

    %{"_csrf_token" => "zoRF14I0ihxcJ_NNQCBPacFX", "live_socket_id" => "users_sessions:Eeg_27_IhdieuOeLPcUpRijLu5V2MnvoUYE-A_xW1og=", "user_token" => <<17, 232, 63, 219, 191, 200, 133, 216, 158, 184, 231, 139, 61, 197, 41, 70, 40, 203, 187, 149, 118, 50, 123, 232, 81, 129, 62, 3, 252, 86, 214, 136>>}

as you can see , non of it is mine

It’s likely something you render in your template. Can you show your template code for path /?

1 Like