Skip to content

Node creation fails when PostgreSQL connector open times out in PostgreSqlStorageAdapter #3050

Closed as not planned

Description

@meshweaver-cloud

What is failing

Node creation (MeshWeaver.Mesh.CreateNode) fails because the PostgreSQL storage layer cannot open a connection to the database host: PostgreSqlStorageAdapter.ExistsAsyncCore() times out while Npgsql tries to establish a new physical connection (NpgsqlConnector.ConnectAsync → TimeoutException), and the CreateNode handler surfaces this as an unexpected node-creation error. The node that failed to be created was a sample-graph data node under the built-in MeshWeaver/samples/Graph content.

Probable cause

Infrastructure-level PostgreSQL connectivity/availability issue — high confidence that this is the mechanism, moderate confidence on the precise trigger. The stack shows the timeout occurred while opening a brand-new connector (not while executing a query and not while waiting on an existing pool slot), which means the database host was unreachable or accepting connections too slowly at that moment. This is corroborated by sibling incidents in the same failure window and on the same pod: incident a56cefad0e4d4b92 shows the identical connection-open timeout from PostgreSqlStorageAdapter.ReadAsyncCore() seconds before and after this event, and its draft already links this PostgreSQL connectivity problem to existing issue Systemorph/MeshWeaver#1310. A database host restart, resource exhaustion, or brief network partition in the cluster would produce exactly this pattern across all storage-adapter call sites simultaneously.

This incident is likely a duplicate symptom of the same root cause as #1310 / a56cefad0e4d4b92 — filed separately only because the top frame and exception text differ. Consider closing as a duplicate once the underlying PostgreSQL availability issue is tracked.

Impact

Low — isolated and transient. A single node creation failed on one pod, with no further occurrences after the brief failure window. The failed node was sample content under MeshWeaver/samples/Graph, so no user data was lost; a retry would succeed once the database is reachable. However, the same connectivity blip took down multiple storage operations at once (see sibling incident), so if this window recurs at higher volume it would block node creation platform-wide — worth confirming the database host's health around that time.

Where to look

  • PostgreSqlStorageAdapter.ExistsAsyncCore() — per the stack trace, plugins-repo/src/MeshWeaver.Hosting.PostgreSql/PostgreSqlStorageAdapter.cs around line 1066 (the framework source is not present in this mesh, so no mesh link).
  • The Npgsql data-source/pool configuration (connection timeout, pool size, OpenNewConnector behavior) used by MeshWeaver.Hosting.PostgreSql.
  • Database host availability in the cluster during the failure window; cross-check sibling incident a56cefad0e4d4b92 and issue Activity tracking fails when PostgreSQL connection pool is temporarily exhausted #1310, which share the identical connection-open timeout.

Also note that CreateNode reports this as a generic "Unexpected error" — consider distinguishing storage-connectivity failures (retryable) from genuine creation errors in the log category, so operators can tell an infra blip from a defect.


Evidence

Fingerprint a06ed666b8b0198b
Category MeshWeaver.Mesh.CreateNode
Severity Error
Top frame MeshWeaver.Hosting.PostgreSql.PostgreSqlStorageAdapter.ExistsAsyncCore(String path, CancellationToken ct)
Namespace memex-cloud
Pods memex-portal-deployment-85859db964-7sqbk
Occurrences 1
First seen 2026-09-02 03:08:52Z
Last seen 2026-09-02 03:08:52Z
Recent log lines
2026-09-02 03:08:52Z memex-portal-deployment-85859db964-7sqbk fail: MeshWeaver.Mesh.CreateNode[0]
      Unexpected error during node creation at MeshWeaver/samples/Graph/Data/PensionFund/BalanceSheetEntry/2024-RealEstate: NpgsqlException: The operation has timed out
      Npgsql.NpgsqlException (0x80004005): The operation has timed out
       ---> System.TimeoutException: The operation has timed out.
         at Npgsql.ThrowHelper.ThrowNpgsqlExceptionWithInnerTimeoutException(String message)
         at Npgsql.Util.NpgsqlTimeout.Check()
         at Npgsql.Util.NpgsqlTimeout.CheckAndGetTimeLeft()
         at Npgsql.Internal.NpgsqlConnector.ConnectAsync(NpgsqlTimeout timeout, CancellationToken cancellationToken)
         at Npgsql.Internal.NpgsqlConnector.RawOpen(NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken)
         at Npgsql.Internal.NpgsqlConnector.<Open>g__OpenCore|209_0(NpgsqlConnector conn, String username, SslMode sslMode, GssEncryptionMode gssEncMode, NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken)
         at Npgsql.Internal.NpgsqlConnector.Open(NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken)
         at Npgsql.PoolingDataSource.OpenNewConnector(NpgsqlConnection conn, NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken)
         at Npgsql.PoolingDataSource.<Get>g__RentAsync|33_0(NpgsqlConnection conn, NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken)
         at Npgsql.NpgsqlConnection.<Open>g__OpenAsync|42_0(Boolean async, CancellationToken cancellationToken)
         at Npgsql.NpgsqlDataSourceCommand.ExecuteReader(Boolean async, CommandBehavior behavior, CancellationToken cancellationToken)
         at MeshWeaver.Hosting.PostgreSql.PostgreSqlStorageAdapter.ExistsAsyncCore(String path, CancellationToken ct) in /home/runner/work/MeshWeaver/MeshWeaver/plugins-repo/src/MeshWeaver.Hosting.PostgreSql/PostgreSqlStorageAdapter.cs:line 1066
         at MeshWeaver.Hosting.PostgreSql.PostgreSqlStorage…[truncated]

Opened automatically from Admin/_LogIncident/a06ed666b8b0198b. Recurrences are folded into this issue rather than opening new ones.

Activity

  1. rbuergi commented on Sep 2, 2026

    @rbuergi
    Contributor

    Consolidation: this is the same defect as #3051, filed twice

    Both issues are the same log line, from the same handler, on the same fault class. They differ only in which storage call in the create pipeline happened to be the first to try to open a connector:

    #3050 (this one) #3051
    Fingerprint a06ed666b8b0198b a56cefad0e4d4b92
    Log category MeshWeaver.Mesh.CreateNode MeshWeaver.Mesh.CreateNode
    Message Unexpected error during node creation at {Path} Unexpected error during node creation at {Path}
    Top frame PostgreSqlStorageAdapter.ExistsAsyncCore PostgreSqlStorageAdapter.ReadAsyncCore
    Fault NpgsqlException → TimeoutException in PoolingDataSource.OpenNewConnector identical
    Occurrences 1 (2026-09-02 03:08:52Z) 9 (2026-08-23 19:02 → 2026-09-02 03:09)
    Pods ...-85859db964-7sqbk 3 pods, incl. ...-85859db964-7sqbk

    The create handler's chain opens with persistence.Read(node.Path, …) and probes Exists for the NodeType a few steps later. Both reach the same terminal onError arm of HandleCreateNodeRequest, and both were answered identically. Which of the two frames appears in a given capture is a property of when in the chain the store went away — not of a second defect. Two fingerprints, one bug.

    Verdict: one defect. #3051 survives — it carries 9 occurrences across 3 pods and 10 days of history, where this one carries a single sample; the survivor is the issue with the evidence.

    This issue's own body reached the same conclusion ("This incident is likely a duplicate symptom of the same root cause as #1310 / a56cefad0e4d4b92 … Consider closing as a duplicate"), and it is right.

    What is being fixed, on #3051

    The fix is not a retry and not a widened timeout. The bounded retry already exists and already ran (TransientStorageFaults.RetryTransientConnect, #2521 — 250 → 500 → 1000 ms, then the last error surfaces), so a fault that reaches the handler's terminal arm is one whose budget is honestly spent.

    What was missing is the answer: a create whose store could not be REACHED was reported as NodeCreationRejectionReason.Unknown under the words "Unexpected error during node creation" — a verdict, when the create had never been attempted. That distinction has teeth: a caller that reads "refused" and mints a fresh id on its next attempt writes a duplicate (#2229's shape). It is now answered Unavailable ("not evaluated, retry is meaningful", #1446), with a log line that names the store instead of the create — the same correction #3031 landed one layer up for a layout area's render (#2876).

    Closing as a duplicate of #3051. The last sentence of this issue's own "Where to look" section is what got implemented.

  2. rbuergi commented on Sep 2, 2026

    @rbuergi
    Contributor

    Duplicate of #3051 — same log line, same handler, same fault class; the two fingerprints differ only in which storage call happened to try opening a connector first. Reasoning and the fix's scope are in the comment above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions