Skip to content

Commit 6d35aaa

Browse files
committed
fix: Avoid reference types in struct initialisation
Erlang/OTP 28 no longer allows regex literals in struct defaults, due to non-serializable Reference types. Instead, it sets it in the `new` function.
1 parent 0f5161e commit 6d35aaa

File tree

2 files changed

+113
-2
lines changed

2 files changed

+113
-2
lines changed

lib/container.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ defmodule Testcontainers.Container do
2323
labels: %{},
2424
auto_remove: false,
2525
container_id: nil,
26-
check_image: ~r/.*/,
26+
check_image: nil,
2727
network_mode: nil,
2828
reuse: false,
2929
force_reuse: false,
@@ -61,7 +61,7 @@ defmodule Testcontainers.Container do
6161
A constructor function to make it easier to construct a container
6262
"""
6363
def new(image) when is_binary(image) do
64-
%__MODULE__{image: image}
64+
%__MODULE__{image: image, check_image: ~r/.*/}
6565
end
6666

6767
@doc """

testcontainers-elixir-1.18-fix.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# Testcontainers Elixir 1.18 Compatibility Fix
2+
3+
## GitHub Issue
4+
5+
**Title:** Compilation error with Elixir 1.18: "cannot escape #Reference" in struct defaults
6+
7+
**Description:**
8+
9+
The testcontainers-elixir library fails to compile on Elixir 1.18+ due to a breaking change in how regex literals are handled in struct defaults.
10+
11+
### Error Message
12+
```
13+
== Compilation error in file lib/container.ex ==
14+
** (ArgumentError) invalid value for struct field check_image, cannot escape #Reference<...>.
15+
The supported values are: lists, tuples, maps, atoms, numbers, bitstrings, PIDs and remote functions in the format &Mod.fun/arity
16+
```
17+
18+
### Root Cause
19+
Elixir 1.18 with Erlang/OTP 28 no longer allows regex literals to be used as struct default values because they contain internal `Reference` types that cannot be serialized during compilation. This is documented in the [Elixir 1.18 release notes](https://hexdocs.pm/elixir/changelog.html):
20+
21+
> "Erlang/OTP 28 no longer allows regexes to be defined in the module body and interpolated into an attribute"
22+
23+
### Current Code (lib/container.ex:26)
24+
```elixir
25+
defstruct [
26+
check_image: ~r/.*/, # This fails on Elixir 1.18+
27+
# ...
28+
]
29+
```
30+
31+
### Environment
32+
- Elixir: 1.18.4
33+
- Erlang/OTP: 28
34+
- testcontainers: 1.12.0
35+
36+
## Fix Plan
37+
38+
### 1. **Fix the struct definition** (`lib/container.ex:26`)
39+
```elixir
40+
# Change from:
41+
check_image: ~r/.*/,
42+
43+
# To:
44+
check_image: nil,
45+
```
46+
47+
### 2. **Update constructor functions** to handle regex initialization
48+
Look for functions like `new/1` or similar constructors and ensure they set the default regex:
49+
50+
```elixir
51+
def new(opts \\ []) do
52+
%__MODULE__{
53+
check_image: Keyword.get(opts, :check_image, ~r/.*/),
54+
# ... other fields
55+
}
56+
end
57+
```
58+
59+
### 3. **Search for other potential regex literals in struct defaults**
60+
Check if there are any other structs with similar issues:
61+
```bash
62+
grep -r "~r" lib/ | grep "defstruct"
63+
```
64+
65+
### 4. **Update any container-specific modules**
66+
Check if `RedisContainer`, `PostgresContainer`, etc. have similar issues in their struct definitions.
67+
68+
### 5. **Test the fix**
69+
- Compile the library: `mix compile`
70+
- Run existing tests: `mix test`
71+
- Verify Redis container specifically works
72+
73+
### 6. **Create backwards compatibility**
74+
Ensure the fix works with both older and newer Elixir versions by testing that:
75+
- The `new/1` functions properly initialize the regex
76+
- Existing code using the containers continues to work
77+
- The default behavior remains the same (accepts any image by default)
78+
79+
This is a minimal, targeted fix that maintains backward compatibility while resolving the Elixir 1.18 compilation issue.
80+
81+
## Implementation Steps
82+
83+
1. **Navigate to forked repository:**
84+
```bash
85+
cd /Users/jesse/src/github.com/jesse-c/testcontainers-elixir
86+
```
87+
88+
2. **Create feature branch:**
89+
```bash
90+
git checkout -b fix/elixir-1.18-compatibility
91+
```
92+
93+
3. **Make the changes:**
94+
- Edit `lib/container.ex:26` to change `check_image: ~r/.*/,` to `check_image: nil,`
95+
- Find and update constructor functions to initialize the regex at runtime
96+
- Search for any other similar issues
97+
98+
4. **Test the fix:**
99+
```bash
100+
mix compile # Should now work without errors
101+
mix test # Ensure existing functionality works
102+
```
103+
104+
5. **Commit and push:**
105+
```bash
106+
git add .
107+
git commit -m "Fix Elixir 1.18 compatibility: move regex from struct default to runtime init"
108+
git push origin fix/elixir-1.18-compatibility
109+
```
110+
111+
6. **Create Pull Request** to the original testcontainers-elixir repository

0 commit comments

Comments
 (0)