Skip to content

[BUG] listThreads/listMessages in libsql and pg stores return empty on DB errors instead of throwing #17783

@JigyasuRajput

Description

@JigyasuRajput

Describe the Bug

The paginated memory read methods in the libsql store catch database errors, log them, and then return an empty result like { threads: [], total: 0, hasMore: false } instead of re-throwing. So a failed read looks exactly like a read that genuinely found nothing.

That's a problem because a transient SQLITE_BUSY, a locked table, or a dropped connection gives the caller the same response as "this resource has no threads/messages." Nothing is thrown, so the caller has no way to tell the store failed. There's only a log line.

Where I noticed the practical impact: an agent reading conversation history while the DB is briefly locked gets back [] and acts like the user has no history. If something downstream then writes state based on that empty read, real data can get dropped, and it all happens silently.

Affected code in stores/libsql/src/storage/domains/memory/index.ts:

  • listMessages, catch block at lines 443-465
  • listThreads, catch block at lines 1149-1175
  • listMessagesByResourceId, same pattern
} catch (error) {
  const mastraError = new MastraError({ /* THIRD_PARTY ... */ }, error);
  this.logger?.error?.(mastraError.toString());
  this.logger?.trackException?.(mastraError);
  return { threads: [], total: 0, page, perPage: perPageForResponse, hasMore: false };
}

This already looks like a known issue that just wasn't applied everywhere. The spanner store throws here, and it has a regression test that spells out the intended behavior:

// stores/spanner/src/storage/index.test.ts
describe('error propagation (no empty-on-error)', () => {
  // Regression guard: backend failures must propagate as MastraError so
  // callers can distinguish "no data" from "store unavailable". The
  // prior implementation swallowed errors and returned {total:0,...}.

So the behavior is currently inconsistent across stores for these same list methods:

Throws (correct) Returns empty on error
spanner, clickhouse, cloudflare-d1, lance libsql, pg, mongodb, upstash, dynamodb, mssql

Worth noting this is only about the paginated list methods (listThreads, listMessages, listMessagesByResourceId). Point reads like getMessagesById return empty even in spanner, and those are out of scope here.

Steps To Reproduce

  1. Set up an agent or storage instance using @mastra/libsql (or @mastra/pg) for memory.
  2. Call storage.listThreads({ ... }) or storage.listMessages({ ... }) while the underlying client fails once. The easiest way is to mock the libsql client's execute to reject a single time with new Error('simulated backend outage').
  3. The call resolves successfully with { threads: [], total: 0, hasMore: false }.
  4. No error is thrown, so the caller cannot tell the difference between a real failure and an empty result.

Link to Minimal Reproducible Example

This is verifiable directly from the catch blocks at the lines listed above, and reproducible with a one-line mock that makes the client reject once. The repo already has the reference behavior in stores/spanner/src/storage/index.test.ts under error propagation (no empty-on-error), and the libsql/pg stores currently would not pass an equivalent test.

Expected Behavior

Backend failures in these list methods should propagate as a MastraError, the same way the spanner store does it, so callers can tell "no data" apart from "store unavailable." Validation errors (USER category) should keep throwing like they do now. Only a genuinely empty result should return an empty payload.

Environment Information

System:
  OS: macOS 26.2
  CPU: (10) arm64 Apple M4
  Shell: 5.9 - /bin/zsh
Binaries:
  Node: 20.17.0
  npm: 10.8.2
  Yarn: 1.22.22

Affected packages:
  @mastra/libsql: 1.12.1
  @mastra/core: 1.42.0-alpha.3
  Same pattern also in: @mastra/pg, @mastra/mongodb, @mastra/upstash, @mastra/dynamodb, @mastra/mssql
Reference (already throws): @mastra/spanner, @mastra/clickhouse, @mastra/cloudflare-d1, @mastra/lance

LLM Provider: N/A (storage layer)
Browser: N/A

Verification

  • I have searched the existing issues to make sure this is not a duplicate
  • I have included sufficient information for the team to reproduce and understand the issue

I'm working on this issue and will raise a PR for the same!

Metadata

Metadata

Assignees

No one assigned

    Labels

    StorageIssues with Mastra Storage adapters for databases and vector storagebugSomething isn't workingeffort:mediumimpact:hightrio-tnt

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions