Character set in Firebird error messages

81 views
Skip to first unread message

Tomasz Tyrakowski

unread,
Aug 28, 2026, 8:47:00 AMAug 28
to firebird-support
Hi

Suppose I set UTF-8 as my client encoding. Now I'm trying to connect to
a remote machine and it turns out the FB server can't open the database
file at the path I provided in the DPB.
Firebird server returns an error, but the error also contains the error
message returned by the underlying server OS.
The question is: what's the encoding of the Firebird error message (I/O
error during "open" operation for file ...), and what's the encoding of
the included server OS error message, when my declared client encoding
is UTF-8? Is it possible to find out which encoding is included in the
error message on the client?
I suppose the Firebird part of the message depends on firebird.msg (and
I can use my own on the client), but the OS part is out of my control.
I did some experiments, and it seems that a Firebird server running on
non-English Windows host returns a localized OS error (an equivalent of
"no such file or directory") encoded as a single-byte ANSI encoding,
with code page most likely matching the Windows OS code page of the
server machine.
It's easy to check/replicate this with isql - the localized OS error
message is mangled and not displayed correctly.
Even worse, the included OS error message treated as UTF-8 may be
impossible to decode at all (invalid UTF-8 sequences).
Dealing with this on the client is difficult, because the client, in
general, may not know the encoding used internally by the server OS.
The Firebird server, on the other hand, has all the necessary
information and could (in theory) encode the OS error message as UTF-8
(the declared client charset). Of course I'm aware that if the client
declares for example CP-1252 and the server runs on a machine with the
OS CP-1250, the translation can be lossy or impossible, but with UTF-8
on the client, virtually all ANSI code pages are supported and the OS
error could be transcoded.

Has any of you guys found a general solution to this problem? Is it even
a problem? Maybe I don't know about something that makes it possible to
decode the OS error message correctly?

best regards
Tomasz

Tomasz Tyrakowski

unread,
Aug 30, 2026, 10:29:57 AMAug 30
to firebird...@googlegroups.com
On 28.08.2026 at 14:46, Tomasz Tyrakowski wrote:
> [...]
>
> The question is: what's the encoding of the Firebird error message (I/O
> error during "open" operation for file ...), and what's the encoding of
> the included server OS error message, when my declared client encoding
> is UTF-8? Is it possible to find out which encoding is included in the
> error message on the client?
To narrow the scope: what I'm really trying to figure out is the
encoding of the string prepared by IUtil::formatStatus(), when the
actual error message includes an error returned by the operating system
of the host the server is running on (which may be in the server OS
language, with unknown encoding). How should I properly convert the
buffer returned by IUtil::formatStatus() to a Unicode string, assuming
my declared client character set is UTF-8?

regards
Tomasz

Dimitry Sibiryakov

unread,
Aug 30, 2026, 11:02:27 AMAug 30
to firebird...@googlegroups.com
Tomasz Tyrakowski wrote 30.08.2026 16:29:
> How should I properly convert the buffer returned by IUtil::formatStatus() to a
> Unicode string, assuming my declared client character set is UTF-8?

Short answer: you cannot.
Long answer: OS error is transferred as an error number, not string and
converted to string on client side. Windows use ANSI function for that so the
result is always in ANSI code page regardless of connection charset. But the
rest of strings are in connection charset. The problem is that
IUtil::formatStatus() convert whole status vector at once so you even cannot
separate these string.
In fact, the only solution for that is a manual handling of status.

--
WBR, SD.

Tomasz Tyrakowski

unread,
Aug 30, 2026, 11:42:38 AMAug 30
to firebird...@googlegroups.com
On 30.08.2026 at 17:02, 'Dimitry Sibiryakov' via firebird-support wrote:
> Tomasz Tyrakowski wrote 30.08.2026 16:29:
>> How should I properly convert the buffer returned by
>> IUtil::formatStatus() to a Unicode string, assuming my declared client
>> character set is UTF-8?
>
>   Short answer: you cannot.

That's what I've figured so far - not without some help from the server.

>   Long answer: OS error is transferred as an error number, not string
> and converted to string on client side.

I don't believe it is so. I've just connected from a Linux isql to a FB
server running on Windows and I'm pretty sure the message Linux isql
shows me is the Windows error message (in Polish), while using the same
isql on the same Linux machine to connect to a Linux server shows an
English message ("No such file or directory").
Besides, it would seem unlikely that a client running on Linux (MacOS,
Android, ...) would know how to translate a Win32 error code into an
error message (it applies to any combination of different server/client
OS's). It can't rely on its own OS to do that, because it's a different OS.
So I guess the _Firebird_ error is transferred as ISC code and converted
to a message client-side, but the included OS error message is sent as a
string. I'm not sure (would have to hunt it down in the Firebird
sources), but all evidence so far supports it.

> Windows use ANSI function for
> that so the result is always in ANSI code page regardless of connection
> charset. But the rest of strings are in connection charset. The problem
> is that IUtil::formatStatus() convert whole status vector at once so you
> even cannot separate these string.
>   In fact, the only solution for that is a manual handling of status.

That can be handled properly only server-side IMHO. The server knows the
OS it's running on and its locale, while the client does not have that
knowledge, so it can't guess which ANSI encoding the server uses in OS
messages (even if the client decided to decode the status by hand, it
won't be able to without this knowledge).

The problem surfaced when one of my users encountered an error with "No
such file or directory", but while connecting to a server running on
Windows with Russian locale, so the included OS error was "Не удается
найти указанный файл", encoded (probably) as CP-1251. Trying to decode
the error message from UTF-8 resulted in invalid UTF-8 sequences.

Anyway, thank you for the information you provided, I'll think about
some workarounds, because it seems it's unsolvable client-side at the
moment.

regards
Tomasz

Dimitry Sibiryakov

unread,
Aug 30, 2026, 11:54:29 AMAug 30
to firebird...@googlegroups.com
Tomasz Tyrakowski wrote 30.08.2026 17:42:
> I don't believe it is so. I've just connected from a Linux isql to a FB server
> running on Windows and I'm pretty sure the message Linux isql shows me is the
> Windows error message (in Polish), while using the same isql on the same Linux
> machine to connect to a Linux server shows an English message ("No such file or
> directory").

It is a happy coincidence that Windows C runtime has the some error codes
matching Linux error codes and can interpret them with strerror() function. Vice
versa it doesn't work: connecting to Windows server from Linux you'll get
"Unknown Win32 error XXX" message.

> That can be handled properly only server-side IMHO.

Yes, all the server need to do is to intercept error in the place it is
raised (StatusArg.cpp:OsError) and transform it into a string immediatelly.
Doable but so far nobody was interested.

--
WBR, SD.

Dimitry Sibiryakov

unread,
Aug 30, 2026, 12:08:38 PMAug 30
to firebird...@googlegroups.com
Tomasz Tyrakowski wrote 30.08.2026 17:42:
> The problem surfaced when one of my users encountered an error with "No such
> file or directory", but while connecting to a server running on Windows with
> Russian locale, so the included OS error was "Не удается найти указанный файл",
> encoded (probably) as CP-1251.

It sounds like the error was produced by Execute Statement. It does
interpretation of the status on server side.

--
WBR, SD.

Vlad Khorsun

unread,
Aug 30, 2026, 12:16:09 PMAug 30
to firebird-support
Tomasz Tyrakowski wrote 30.08.2026 16:29:
> How should I properly convert the buffer returned by IUtil::formatStatus() to a
> Unicode string, assuming my declared client character set is UTF-8?

Short answer: you cannot.
Long answer: OS error is transferred as an error number, not string and
converted to string on client side.

You again speak about things you not understand

Vlad
 

Dimitry Sibiryakov

unread,
Aug 30, 2026, 12:21:04 PMAug 30
to firebird...@googlegroups.com
Vlad Khorsun wrote 30.08.2026 18:16:
>
> You again speak about things you not understand

Ok, now, when here has appeared someone who understands things, I can leave
solution to him.

--
WBR, SD.

Vlad Khorsun

unread,
Aug 30, 2026, 12:23:33 PMAug 30
to firebird-support
>   Long answer: OS error is transferred as an error number, not string
> and converted to string on client side.

I don't believe it is so.

And you right here.
 
I've just connected from a Linux isql to a FB
server running on Windows and I'm pretty sure the message Linux isql
shows me is the Windows error message (in Polish), while using the same
isql on the same Linux machine to connect to a Linux server shows an
English message ("No such file or directory").

  OS errors are interpreted by the network server before being sent to the client.
On Windows it is done using FormatMessageA() with current user lang id  - i.e. 
using lang id of the user account running Firebird server. At this point the code
(internals of fb_interpret()) have no idea about user charset etc.

  I'm not saying it is best and only possible way, just explaining how it works actually. 

Regards,
Vlad

Tomasz Tyrakowski

unread,
Aug 30, 2026, 1:25:31 PMAug 30
to firebird...@googlegroups.com
On 30.08.2026 at 18:23, Vlad Khorsun wrote:
> [...]
> OS errors are interpreted by the network server before being sent to the
> client.
> On Windows it is done using FormatMessageA() with current user lang id -
> i.e.
> using lang id of the user account running Firebird server. At this point
> the code
> (internals of fb_interpret()) have no idea about user charset etc.
>
> I'm not saying it is best and only possible way, just explaining how it
> works actually.
Thanks for the explanation. I'll do some workarounds client-side (e.g.
check whether the error message can be decoded as UTF-8 and doesn't
contain illegal UTF sequences), but that solves only part of the
problem. The localized OS message can (by coincidence) can be
ANSI-encoded, but not contain illegal UTF-8 sequences. This way the
message will be decoded from UTF without errors, but will contain some
garbage in the OS part.
But there's no other way than to accept the things as they are now,
thanks again for clarification.

regards
Tomasz

Tomasz Tyrakowski

unread,
Aug 30, 2026, 1:29:38 PMAug 30
to firebird...@googlegroups.com
On 30.08.2026 at 17:54, 'Dimitry Sibiryakov' via firebird-support wrote:
> [...]
>   It is a happy coincidence that Windows C runtime has the some error
> codes matching Linux error codes and can interpret them with strerror()
> function. Vice versa it doesn't work: connecting to Windows server from
> Linux you'll get "Unknown Win32 error XXX" message.

As I wrote, I connected with isql from _the_same_ Linux machine to a
Windows server and then to a Linux server, and I got different OS error
messages each time.
If "no such file or directory" error codes are accidentally equal on
Win32 and Linux, I would expect to get the same error message twice
(formatStatus gets the same error code and produces the same error message).

>
>> That can be handled properly only server-side IMHO.
>
>   Yes, all the server need to do is to intercept error in the place it
> is raised (StatusArg.cpp:OsError) and transform it into a string
> immediatelly.
>   Doable but so far nobody was interested.

Or maybe improve IUtil.formatStatus so that it would ignore the OS error
instead of producing a string that cannot be decoded in any meaningful way.

Thanks again for the insights.

regards
Tomasz

Tomasz Tyrakowski

unread,
Aug 30, 2026, 1:32:22 PMAug 30
to firebird...@googlegroups.com
On 30.08.2026 at 18:08, 'Dimitry Sibiryakov' via firebird-support wrote:
> [...]
>   It sounds like the error was produced by Execute Statement. It does
> interpretation of the status on server side.

Actually this error popped up on attach, when the database path points
to a non-existent file. My Polish Win32 error message also appears on
attach (when executing "connect" in isql).
Probably execute statement (on external database) would produce a
similar OS error if I specified non-existent DB.

regards
Tomasz

Vlad Khorsun

unread,
Aug 30, 2026, 2:32:47 PMAug 30
to firebird-support
  The obvious workaround is to run Firebird server using user account that tuned 
to use well-known locale (EN-US or same as clients). And don't assume that 
isc_arg_interpreted strings in status-vector are in client's attachment charset.

Hope it helps,
Vlad

Dimitry Sibiryakov

unread,
Aug 30, 2026, 2:58:00 PMAug 30
to firebird...@googlegroups.com
Tomasz Tyrakowski wrote 30.08.2026 19:32:
>
> Actually this error popped up on attach, when the database path points to a non-
> existent file. My Polish Win32 error message also appears on attach (when
> executing "connect" in isql).

Yes, Vlad is right. I missed transformation isc_arg_win32/unix ->
isc_arg_interpreted in Firebird network server.

--
WBR, SD.
Reply all
Reply to author
Forward
0 new messages