Formatter error - bad return value

Hi All,
I’m getting error “FORMATTER ERROR: bad return value” in my log file. Below is my config on windows 11 with OTP 26 and Elixir 1.16. Thank you.

config :logger, :default_handler,
        level: :info,
        handle_otp_reports: true,
        handle_sasl_reports: true

config :logger, :default_formatter,
        format: "$level $date $time $message\n",
        truncate: :infinity

I turned on debugging and realized that the formatter was complaining of a binary value probably due to the encoding not being utf8.

What was producing a non-UTF8 value?

I wanted to edit the answer, but I basically got an error with below description, I’ve truncated the binary values
(RuntimeError) bad return value from Logger formatter Logger.Formatter, got [<<163,...>>, "\n"] after <<109...>>
I ended wrapping the argument to logger in inspect which works, 163 is an extended ascii character which I understand is not mapped directly to utf8 encoding unlike the ascii characters from 127 and below.

I tried<<97, 98, 99, 160>>) which resulted in similar error (RuntimeError) bad return value from Logger formatter Logger.Formatter, got [<<160>>, "\n"] after " info 2024-02-15 19:39:44.778 abc".

Using :unicode.characters_to_binary(msg, :latin1) does the conversion to utf8.

A bit of context, I’m working on an sms application, so basically the app receives sms from a mobile handset.

Why not:

<<97, 98, 99, 160>>
|> inspect()


Oh? Do you happen to have open-source code for encoding / decoding SMS messages in Elixir (or Rust)? I will be writing such code soon and could really reuse some.

What kind of encoding / decoding are we talking about? I do have some years of experience of reading/encoding/decoding data from smartcards (AKA simcards).<<97, 98, 99, 160>>) was to confirm my suspicion that the error was due to the binary encoding, just to reproduce the error.

SMPP library, great library for SMPP. For multipart SMS you have to handle the assembling of the messages into a single message, it’s not handled out of the box.

If you intend to use alphanumeric shortcode with special characters like hyphen and underscore, you’ve to set source_addr_ton and source_addr_npi accordingly.

It’s a great library! All the best sir.


Sadly I just digged the documentation and there is no crystal clear explanation that this is not allowed.

The official signature of log message parameter is:

@type message() :: :unicode.chardata() | String.Chars.t() | report()

To be fair this is the first time I see String.Charts.t() type, I would guess that this is the equivalent of a valid (ascii or utf-8) chars list.

If you take a look at report() type you can also notice that it accepts a map or keywords, I would guess that you can send a map and it will know how to display your binary data instead of using inspect().

What they call PDUs.

Ah good old days, I love binary protocols.

I would recommend you to use elixir and see how powerful it is in making a completely declarative decoder. From the specs it seems like a typical easy to read protocol, even though I would recommend you to get the official ISO spec (if you plan on serious work) to avoid any surprises.

Yeah, for structured logging and it’s able to display the binary without any issue.

1 Like

I love doing binary protocols with Elixir but thing is, I am pressured for time and would appreciate a ready-made library, if there’s any.

I highly doubt, even though, the erlang ecosystem is the best bet you will find it. Would start by finding the official name of the protocol (specified by the ISO) then searching for trace of it in OTP or old erlang libraries.

A word of warning is that sometimes making reason of a full-fledged protocol from telecom ecosystem is slower than implementing a sub-part yourself. I have learned this myself when I wanted to send snmp traps to our client, we ended up sending them with curl as nobody from our team could understand how to configure the erlang client.

1 Like

That’s a fairly valuable advice, thank you.