Erlang OTP 29.0 Released

OTP 29.0

Erlang/OTP 29 is a new major release with new features, improvements as well as a few incompatibilities. Some of the new features are highlighted below.

Many thanks to all contributors!

Highlights

  • Added support for -unsafe attributes for marking functions as unsafe to use. The compiler will by default now generate warnings for calls to functions in Erlang/OTP known to be always unsafe. Furthermore, xref can now be used to find calls to unsafe functions and functions that lack documentation.

  • The SSH daemon now defaults to disabled for shell and exec services, implementing the “secure by default” principle. This prevents authenticated users from executing arbitrary Erlang code unless explicitly configured.

  • The SFTP subsystem is no longer enabled by default when starting an SSH daemon.

  • In SSL, the post quantum hybrid algorithm x25519mlkem768 is now the most preferred key exchange group in the default configuration.

  • The module io_ansi allows the user to emit Virtual Terminal Sequences (also known as ANSI sequences) to the terminal in order to add colors/styling to text or to create fully fledged terminal applications.

  • The new ct_doctest module allows the user to test documentation examples in Erlang module docs and documentation files.

  • The ignore_xref attribute has been handled as a post-analysis filter by build tools such as Rebar3. In this release, [xref] itself does the filtering, ensuring that all tooling that calls xref for any purpose can rely on these declarations to just work.

General

  • In the default code path for the Erlang system, the current working directory (.) is now in the last position instead of the first.

  • There is no longer a 32-bit Erlang/OTP build for Windows.

New language features

  • Native records as described in EEP-79 has been implemented. A native record is a data structure similar to the traditional tuple-based records, except that is a true data type. Native records are considered experimental in Erlang/OTP 29 and possibly also in Erlang/OTP 30.

  • The new is_integer/3 guard BIF makes it possible to easily verify that a value is both an integer and within a certain range. For example: is_integer(I, 0, 100)

  • Multi-valued comprehensions according to EEP 78 are now supported. For example, [-I, I || I <- [1, 2, 3]] will produce [-1,1,-2,2,-3,3].

  • By enabling the compr_assign feature, it is now possible to bind variables in a comprehensions. For example: [H || E <- List, H = erlang:phash2(E), H rem 10 =:= 0]

Compiler and JIT improvements

  • In the documentation for the [compile] module, there is now a section with recommendations for implementors of languages running on the BEAM.

  • The JIT now generates better code for matching or creating binaries with multiple little-endian segments.

  • The compiler will generate more efficient code for map comprehensions with constant values that don’t depend on the generator. Example: #{K => 42 || K <- List}

Compiler warnings

There are several new compiler warnings enabled by default. For each such warning, there is an option to disable it.

  • There will now be a warning when using the catch operator, which has been deprecated for a long time. It is recommended to instead use try…catch but is also possible to disable the warning by using the nowarn_deprecated_catch option.

  • There will now be a warning when exporting variables out of a subexpression. For example: file:open(File, AllOpts = [write, {encoding,utf8}]). This warning can be disabled using the nowarn_export_var_subexpr compiler option.

  • There is a new option warn_obsolete_bool_op that instructs the compiler to emit warnings for the and and or operators. It is recommended to instead use the modern andalso and orelse operators, or , and ; in guards.

  • The compiler will now warn for matches such as {a,B} = {X,Y}, which is better written as {a=X,B=Y}. This warning can be disabled using the nowarn_match_alias_pats option.

For a long time, there has been a warning for using the obsolete guard tests (such as list(L) instead of is_list(L). In Erlang/OTP 30, the old guards will be removed from the language.

STDLIB

  • There are new functions for randomly permutating a list: rand:shuffle/1 and rand:shuffle_s/2.

SSH

  • The default key exchange algorithm is now mlkem768x25519-sha256, a hybrid quantum-resistant algorithm combining ML-KEM-768 with X25519. This provides protection against both classical and quantum computer attacks while maintaining backward compatibility through automatic fallback to other algorithms when peers don’t support it.

For a full list and more details about new features and potential incompatibilities see the README.

23 Likes

Сhecksums (SHA256.txt, MD5.txt) are missing.

1 Like

I missed the discussions on those. What’s wrong with them?

1 Like

If you are writing Elixir code, nothing is wrong. Elixir’s and is the same as Erlang’s andalso, and Elixir’s or is the same as Erlang’s orelse.

In Erlang, and and or have the “wrong” precedence, forcing you to write parentheses or get the wrong result. For more details see:

Also, warnings for and and or not enabled by default. I got that wrong in the highlights for RC1 and that got included in the highlights. I’ve edited @proxyles’s post, and the release note in the release is correct. Here is the correct note:

There is a new option warn_obsolete_bool_op that instructs the compiler to emit warnings for the and and or operators. It is recommended to instead use the modern andalso and orelse operators, or , and ; in guards.

7 Likes

Congratulations to all involved in release 29.0 !

3 Likes

Here is a blog post about the highlights in the release:

9 Likes

I found two issues when I visited
https://www.erlang.org/downloads

  1. On the right there are four prominent rectangles.
    The bottom one is labelled “View Documentation”.
    Clicking on it leads to
    Page not found
    which reads “Page not found”.
    I expected it to lead to the documentation for 29.0.1
  2. This is explicitly a page about 29.0.1.
    “Pre-built binary packages” has a line
    “For Ubuntu and Debian: apt-get install erlang”
    I am running Ubuntu 24.04 LTS under WSL2.
    That’s how I installed Erlang on this laptop.
    According to apt update,
    I’m fully up to date.
    But what I have is OTP 28 on emulator 16.2 (confusing).
    If you follow the instructions, then,
    you won’t get the release 29 you were expecting.

FOr what it’s worth, aot list reports 104 erlang-related packages.
Is there an explanatory list of them somewhere?

1 Like

Thanks for the bug report! I’ve fixed the links to work as they should and added a small comment explaining that most OS package manager lag behind on versions.

The placeholder text for the search box is Search erlang.org however at any screen size I see it truncated:
Screenshot 2026-05-29 at 4.43.46 PM

What browser + OS are you using?

For me with chrome on macOS, the text is truncated only when the screen width is smaller than 1200px, and then at 990px it collapses further to the “mobile” view.

Chrome version 148.0.7778.179 on macOS Tahoe 26.5.

I’m running exact same chrome on macOS Tahoe 26.4.1. How very odd.

Turns out in Chrome settings I have font size Large, changing it to Medium (recommended) does display the whole string.

Sorry for the noise.