Skip to content

config/3 re-orders keyword lists while deep-merging #14461

Closed as not planned
Closed as not planned
@florius0

Description

@florius0

Elixir and Erlang/OTP versions

Erlang/OTP 27 [erts-15.2.3] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit]

Elixir 1.18.3 (compiled with Erlang/OTP 27)

Operating system

Darwin MacBook-Pro 24.4.0 Darwin Kernel Version 24.4.0: Fri Apr 11 18:32:50 PDT 2025; root:xnu-11417.101.15~117/RELEASE_ARM64_T6041 arm64

Current behavior

Consider the following config.exs

import Config

config :config_reorder_reproduction, :key,
  a: 1,
  b: 2,
  c: 3

config :config_reorder_reproduction, :key,
  a: 2,
  b: 1

Application.get_env(:config_reorder_reproduction, :key) returns [c: 3, a: 2, b: 1].

Expected behavior

From my point of view, the Application.get_env(:config_reorder_reproduction, :key) should return [a:2, b: 1, c: 3, since in the first config/3 they were configured in that particular order, and keyword-lists are ordered.

Use case

When configuring something similar to pipeline, .e.g:

# config/config.exs
import Config

config :my_app, MyApp.Pipline1, [
    {MyApp.Pipline1.Step1, ...},
    ...
    {MyApp.Pipline1.StepN, ...},
  ]

# config/runtime.exs

config :my_app, MyApp.Pipline1, [
    {MyApp.Pipline1.Step1, secret: System.fetch_env!("PIPELINE_1_STEP_1_SECRET")}
  ]

it is convenient only to configure secrets for the steps in runtime.exs, and not copy-paste the whole pipeline configuration, but currently the bug breaks the order on which MyApp.Pipline1 may actually rely.

PS

I suppose one could write the steps explicitly and then have only the values of the particular key/step be merged, but it would be better to have this behaviour documented.

# config/runtime.exs

config :my_app, MyApp.Pipline1, [
    {MyApp.Pipline1.Step1, secret: System.fetch_env!("PIPELINE_1_STEP_1_SECRET")}
    ....
    {MyApp.Pipline1.StepN, []}
  ]

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions