You are not logged in.
This is good news for the mORMot community.
Thanks.
This happened several times during testing.
Since the database wasn't generating the auto-increment key, I thought the problem was related to my class definition.
Anyway, for now I used soft delete.
I defined my model like this:
TOrmTestA = class(TOrm)
private
fMSG: RawUTF8;
published
property MSG: RawUTF8 read fMSG write fMSG;
end;The tables were created in PostgreSQL using CreateMissingTables.
I’m using the interface and ORM to operate on the table.
When I insert a record and then delete it, and then create a new record, the new record takes the ID of the deleted one.
Is this standard behavior? How can I change it?
@flydev, in you log did exception happen when TRestServerDB Begin/End CurrentThread happen? Or in @kabiri happen by chance.
At the beginning of each log, I can see `BeginCurrentThread`, but I don’t see `EndCurrentThread`.
However, the error does not occur immediately after that.
So just use useHttpAsync in in the meantime.
OK.
@flydev
Thanks for checking.
Sometimes it stops inside `mormot.db.sql.postgres`.
As I mentioned earlier, I had already pointed out which function it stops in.
Thanks for checking. As I mentioned, it happens randomly — sometimes immediately after startup, and sometimes after an hour.
please set DBProps.UseCache := True;. Any reason for False?
Since `DBProps.UseCache` was not explicitly set and I was getting this error, I changed it to `False`.
It happened in this sample code as well.
I also included the log files in the RAR archive.
The structure of this application is exactly the same as the main application. In this application as well, I didn’t encounter any errors, as I mentioned before.
However, this one uses a single table in the endpoints, while the main application uses multiple tables and more complex reports.
The database connection is set up like this:
{$ifdef DBZeos}
DBProps := TSqlDBZeosConnectionProperties.Create('zdbc:postgresql://' + Host,DBName, DBUser, DBPass);
{$else}
DBProps := TSqlDBPostgresConnectionProperties.Create(Host, DBName, DBUser, DBPass);
{$endif}
DBProps.UseCache := False;
DBProps.ReconnectAfterConnectionError := True;*DBZeos is not being used.
I set ptOneFilePerThread.
I did not change the connection properties threading mode, so it is still using the default value.
As you suggested earlier, I already switched to sicShared. The previous log was also generated with that setting.
I have not changed TInterfaceMethodOptions at all.
For each table, I register it like this:
VirtualTableExternalRegister(Model, TOrmAlarm, DBProps);
And each service is defined like this:
Server.ServiceDefine(TViAlarmService, [IViAlarmService], sicShared);
Inside the services, I only use ORM.
New log : https://mega.nz/file/8k4SUYyQ#f5pgGyFb6 … 7_m5hd2B7s
Look like interface created threads using db connection in wrong way, provide some source for ViTaskService.GetDetail, ViTaskService.ViewTask.
Or you call this methods from different thread!
I implemented the interface the same way as the others. Only ORM is used inside these methods.
ViewTask only receives an ID and performs a simple update.
GetDetail reads values from several tables and puts them into a single JSON object.
Compress the logs in a zip and make a link here.
Log file :
https://mega.nz/file/s5hkBChA#geEYuBua8 … cJDp4KyHhw
@ttomas
Ok - Thanks
---Edit---
It failed and generated 9 log files. However, after reviewing the logs, I couldn’t identify the problem.
Can you log thread/db connect/disconnect. Look like connect, prepare statement, execute prepared statement, disconnect (all OK). Then on next req you have connect, execute prepared statement from previous connection, without prepare statement.
Unfortunately, I don’t know how to do that, since thread and connection management is handled internally by mORMot.
If mORMot doesn’t log this information with `TSynLog.Family.Level := LOG_VERBOSE;`, I think I would need to add these logs myself directly into the mORMot source code.
I switched back to `useHttpSocket` again.
The database currently contains only about 20 records.
Now I got this error:
`Project Vi.exe raised exception class ESqlDBPostgres with message 'TSqlDBPostgresLib Exec failed: [insufficient data in "T" message]'`
The exception occurred in `mormot.db.sql.postgres`, inside `TSqlDBPostgresStatement.ExecutePrepared`, at this line:
`PQ.Check(c.fPGConn, 'Exec', fRes, @fRes, {andclear=}false);`
It was triggered through `TRestStorageExternal.EngineRetrieve` and `TOrm.Create`.
BTW don't you have DPI (Deep Packet Inspection) enabled on your network?
No, I haven't enabled it. The server is currently running on localhost.
So far, I haven’t seen any errors when using `useHttpAsync` together with `TSqlDBConnectionProperties`.
Are you sure sicPerThread is needed?
Please follow the rules and don't put logs directly in the forum stream.
At first, I was using sicShared with useHttpSocket.
I thought it might work better if each instance had its own thread, so I switched to sicPerThread.
Now I’ve changed it back to sicShared and switched to useHttpAsync.
I’ll test it and see whether the database issue still happens.
Understood, I’ll remove the logs.
What I tried to ask there was not a new or overly simple piece of code, but a reproducible sample based on your actual code, with the relevant services, server initialization, database initialization, and related code simplified as much as possible.
The code is not owned by me, so I cannot share the original project directly.
However, I already simplified the same codebase.
The server initialization, service registration, and the database access layer were not changed.
Only the models were reduced to two simple models, and the service layer was reduced to two services.
I also wrote a new and much simpler client to communicate with the server.
However, after testing the simplified version for about one hour, the issue did not occur.
In the main application, I also tried repeating the same actions many times, and the issue still did not happen consistently.
At first, I thought it was related to navigating from one menu to another, but later I realized that is not the case. It just happens from time to time.
Sometimes it happens 5 minutes after startup, and sometimes after one hour.
Since I could not reproduce the issue in the simplified version, I did not upload it anywhere yet.
I will continue testing it further, and if I manage to reproduce the issue there as well, I will upload it.
However, the error message itself suggests that two threads are using the same database connection at the same time, and this is not something I directly control in the application.
Use the async HTTP server to have a stable pool of threads.
OK, I’ll do it.
Well, now I’m getting this error:
Project Vi.exe raised exception class ESqlDBPostgres with message
“TSqlDBPostgresLib Exec failed: [message contents do not agree with length in message type "T"
server sent data ("D" message) without prior row description ("T" message)]”.It happened.
TSqlDBPostgresStatement object 016914ac4940 was previously used by conn-2 (ThreadID=29bc) across multiple queries (lines 201–232).
After conn-2 called EndCurrentThread, the same statement object was reused by conn-4 (ThreadID=23376) — visible at line 273.
When conn-4 (ThreadID=23376) and conn-5 (ThreadID=24728) both called Prepare simultaneously on statement objects 016914ac4940 and 016914ac4ac0 respectively, a PostgreSQL protocol-level exception was raised:
message contents do not agree with length in message type "T" / server sent data ("D" message) without prior row description ("T" message)
line 309-323
Both threads were handling the same two service methods (ViTaskService.ViewTask and ViTaskService.GetDetail) concurrently, using sicPerThread instance mode.
The Statement field in the exception object is null, suggesting the statement reference was lost or corrupted at the time of the error.
Environment:
mORMot version: 2.4.14728
PostgreSQL: 127.0.0.1:5432, libpq v170006
OS: Windows 10 x64
App: x64
Service instance mode: sicPerThread
Thread pool size: 32
As far as I understood, this happens because two or more threads are using the same database connection at the same time.
I thought that with this approach there would be only one thread for database access.
However, the error does not occur immediately after startup.
Sometimes it happens after 5 minutes, sometimes after 30 minutes.
I tried using tmMainConnection. This time it does not show an error, but the server suddenly freezes and after a short time it gets terminated.
Now I have removed tmMainConnection, but still no error has appeared yet, so I haven’t included a new log.
Does this connection method help?
{$ifdef DBZeos}
DBProps := TSqlDBZeosConnectionProperties.Create('zdbc:postgresql://'+Host,
DBName, DBUser, DBPass);
{$else}
DBProps := TSqlDBPostgresConnectionProperties.Create(Host, DBName, DBUser, DBPass);
{$endif}
DBProps.UseCache := False;
DBProps.ReconnectAfterConnectionError := True;
{$ifdef DBZeos}
DBProps.ThreadingMode := tmMainConnection;
{$else}
(DBProps as TSQLDBConnectionPropertiesThreadSafe).ThreadingMode := tmMainConnection;
{$endif}Just sayin, without any code to read and/or reproducible sample it's really hard to help.. if you have any ai tool at hand then just ask it to extract a sample, and even better, install a debugging skill on it and throw it on your codebase.
I created a sample code, but it didn’t produce any errors.
I perform JWT validation in Server.OnBeforeURI.
@ab I didn’t use pointers in my code.
Everything is wrapped in try/finally blocks.
I have 21 models, 87 endpoints, and 10 services.
I used interfaces.
Also, I created the HTTP server like this:
Http := TRestHttpServer.Create(Port, [Server], '+', useHttpSocket);And the server is created as:
Server := TRestServerDB.Create(Model, ':memory:', False);@ttomas : What exactly was your issue?
@ab
I created a small program and sent a large number of concurrent requests, and there were no errors.
This program is different from the main application.
In the main application, I wrote a function for `Server.OnBeforeURI`, and inside that function I have the following code:
var AuthService := TViAuthService.Create;
try
CurrentTenantID := TenantID;
CurrentUserID := UserID;
var ORM := Ctxt.Server.Orm;
AuthService.IsValidLogin(ORM, CurrentTenantID, CurrentUserID, CurrentUserRole);
finally
AuthService.Free;
end;Could this be the reason for these errors?
----Edit----
I removed this code as well, but it still happened.
I only used the ORM.
I should create a smaller sample project, and if the same issue still occurs, I will send it to you.
I changed all services from:
Server.ServiceDefine(TViAuthService, [IViAuthService], sicShared);to
Server.ServiceDefine(TViAuthService, [IViAuthService], sicPerThread);but the error still occurs.
Once again, the error happens inside `libpq.dll`.
@flydev @danielkuettner
I removed the DLL files from next to the application and the error appeared, so it seems it is using those DLLs. Maybe it’s related.
I registered the services like this:
Server.ServiceDefine(TViAuthService, [IViAuthService], sicShared);Would `sicPerThread` help?
In my application I don’t have multiple threads, but the client can send asynchronous requests. I assumed that on the server side it would be handled internally.
Are you sure the libpq library is in the same version than the server?
Yes.
After installing the new version, I copied it from
C:\Program Files\PostgreSQL\18\pgAdmin 4\runtime
and placed it next to my application.
It happened again. This time the error was:
Project Vi.exe raised exception class EZSQLException with message
'SQL Error: message contents do not agree with length in message type "T"
server sent data ("D" message) without prior row description ("T" message)
Code: 7
SQL: select ID,TenantID,Email,FullName,PasswordHash,Role,AvatarUrl,CreatedAt
from public.User where ID=?'.After that, the application raised the following exception:
Project Vi.exe raised exception class $C0000005 with message
'c0000005 ACCESS_VIOLATION'.The client is using HTMX.
After several hours of working with the application, and repeatedly opening and closing menus, the following error suddenly appeared:
Project Vi.exe raised exception class EZSQLException with message
'SQL Error: insufficient data in "T" message
Code: 7
SQL: select ID,Name,Slug,Plan,OwnerID,IsActive,MaxMembers,CreatedAt
from public.Tenant where ID=?'.After that, the application no longer responds to any requests.
This is how I established the connection:
DBProps := TSqlDBZeosConnectionProperties.Create('zdbc:postgresql://' + Host, DBName, DBUser, DBPass);Have you installed 'Zeos' before using it as a DB connection?
No, I haven’t installed it. I thought it didn’t require installation. I’ll install it now.
The `Zeos.inc` file used in `mormot.db.sql.zeos` cannot be found.
Could you try with the Zeos client and see if it is a mormot direct access unit problem?
I am AFK those days, so I can't test anything.
Ok, thanks. I’ll check it and let you know.
Isn’t there any solution?
It’s really frustrating. Right now, even during testing with no users, it keeps getting stuck and I have to restart the service. What should I do when there are many users?
@ab
I updated it and everything was working fine.
After some time—without rapidly switching between menus and without any errors—everything stopped working.
The application reaches this line but never returns from it:
u := TOrmUser.Create;
try
if not Self.Server.Orm.Retrieve('Email=?',[],[Email],u) thenI was using PostgreSQL 17.6-2. I’ll upgrade to PostgreSQL 18.3-2 and test it.
Maybe the issue was related to this: https://www.postgresql.org/message-id/2 … .pgh.pa.us
I'm using mORMot with PostgreSQL, and I suddenly started getting this error:
Project Vi.exe raised exception class ESqlDBPostgres with message:
TSqlDBPostgresLib Exec failed:
[lost synchronization with server: got message type "lost synchronization with server: got message type"]After this error occurs, the application can no longer connect to the database unless restarted.
Here is how I initialize the connection:
Model := CreateViModel;
DBProps := TSqlDBPostgresConnectionProperties.Create(
Host, DBName, DBUser, DBPass
);
DBProps.UseCache := False;
DBProps.ReconnectAfterConnectionError := True;
VirtualTableExternalRegister(Model, TOrmTenant, DBProps);
...Additional details:
The issue seems to happen when rapidly switching between menus in the client (HTMX-based UI).
It looks like multiple concurrent requests may be involved.
After the error, even reconnection does not recover properly.
Questions:
Could this be related to connection reuse or thread safety in mORMot?
Should I be using a connection pool or per-thread connection instead?
Is there a known issue with PostgreSQL driver synchronization in such scenarios?
Any guidance or similar experiences would be appreciated.
![]()
You can try with
Ctxt.OutCookie['myCookie']:='MyValue';
Thanks a lot, that really helped. It’s working now.
I have created a server and interface that work well, and my function returns RawJSON output. In that function, I want to send a cookie in the header along with the response.
For this purpose, I used the following code:
var Ctxt: TRestServerURIContext;
Ctxt := CurrentServiceContext.Request;
Ctxt.Call^.OutHead := Trim(Ctxt.Call^.OutHead) + #13#10 + ...
However, it does not appear in the Response Headers section of the browser.
Where is the problem?
Thanks.
Let me see how I can integrate it with my own project.
I forgot to tell that if you want to play with it, I ported the project on mORMot v2 some months ago and I can publish it.
Yes, I would appreciate that.
dear @ab
I realized that in ServiceRegister, there is a ByPassAuthentication property.
Because of that, I didn't correctly exclude the URL in OnBeforeUri. Instead, I wrote a separate service for it and excluded it during registration using ByPassAuthentication.
On the server, I added the JWT value using JwtForUnauthenticatedRequest.
I configured the authentication using AuthenticationRegister with TRestServerAuthenticationDefault (I also tested other values).
When I send a POST request to my URL, I receive the JWT token.
However, when I send this token to another URL using the Bearer token, I get the following error:
{
"errorCode": 403,
"errorText": "Authentication Failed: Invalid signature (0)"
}If I stop the program, comment out the AuthenticationRegister line, and run the program again, sending the same previous token through my POST, there’s no error.
But the previously excluded URL now gives this error:
Invalid Bearer [jwtNoToken].While tracing, I noticed that HandleAuthentication is triggered by AuthenticationRegister, which causes the JWT authentication to not be executed.
How can I fix this issue?
@flydev
Thanks
It would be great to add a new authentication method.
Using IdemPChar() was suitable for uppercase and lowercase letters, but it differentiated between "." and "/".
To fix the problem, I used this code: StringReplace(Ctxt.Call^.Url,'.','/',[rfReplaceAll])
Unfortunately, I was unable to use TBinaryCookieGenerator.
Hello Michalis,
I have been following Castle Game Engine for many years, but I have not used it yet.
It is a great work, I hope you succeed.
It's a good thing that you used MORMOT 2.
Thanks, I’ll try it.
I don't know what database you use, but it is a simple ON DELETE RESTRICT in PostgreSQL. It throws up a 23503 foreign key violation error code. See https://www.postgresql.org/docs/current … aints.html. And the example you cited is even discussed on the page.
JD
All relational databases operate this way and do not allow deletion.
I said the reason for this is to provide a more appropriate message to the user.
When the primary key of my table is registered in several other tables, I give the user more accurate and clearer information.
Of course, everyone uses their own approach.
Hello dear @AB
I have a function for generating JWT tokens, one for validating them, and another for revoking them.
I created a whitelist for URLs that don’t require authentication and a blacklist for tokens that haven’t expired but have been revoked.
In the `OnBeforeURI` event, if the URL is in the whitelist, I skip token validation and let the request proceed.
If the URL isn’t in the whitelist, I validate the token. If the token is valid and not in the blacklist, authentication is completed, and the corresponding method for that URL is executed.
I did all this because I couldn’t find an automatic solution for this in mORMot2.
I have two questions:
1. Is there no automatic solution for this, and do I have to handle it this way?
2. My problem is with URLs that have slight variations — for example, `api/Auth.Login` and `api/Auth/Login` are both valid. Is there a way to avoid adding multiple similar URLs to the whitelist?
@JD
It’s true that my work increases.
Managing tables and dependencies becomes difficult and time-consuming, and development must be done carefully.
However, in return, I can show more understandable messages to the end user.
Imagine a software user wants to delete a product.
I check the inventory table and inform them that the product cannot be deleted because it still exists in the inventory.
Or I let them know that the product is part of a sales invoice and therefore cannot be deleted.
Hello
I have created the ORM.
I have also established the connection to the SQL Server database.
I have created the database on the sql server(manully).
However, the CreateMissingTables() command does not create the tables.
TMainRestServer = class(TRestServerFullMemory)
private
FConnectionPool: TSqlDBFireDacConnectionProperties;
Model: TOrmModel;and
aServer := TMainRestServer.Create;
aServer.Model:=TOrmModel.Create([TormUnits]);
VirtualTableExternalRegister(aServer.Model,[TormUnits],aserver.FConnectionPool);
HttpServer := TRestHttpServer.Create('8080', [aServer], '+', HTTP_DEFAULT_MODE,4 );
HttpServer.AccessControlAllowOrigin := '*';
aServer.Server.CreateMissingTables();Which part did I do wrong?
I think you don't understand what is being proposed in this thread. The proposal is for mormot to prevent a record from being removed from the database if the record is being used by some property of another object that references this table. this will to avoid inconsistency in the database or the table that references the deleted record being set to ZERO as mormot does today.
The issue of creating the FK is just something additional to prevent the programmer from using a delete outside the ORM from also leaving the database inconsistent.
I know what you're saying, but I still prefer to control the table dependencies myself. When I delete a value in one table and know it's used in another table (like master/detail tables, etc.), I use a select to make sure the record isn't being used in the related tables. The benefit of this method is that my API tells the user they cannot delete this record because it is being used in the (table name) table.