Skip to content

Intermittent 'Namespace not found' on local backend: add() uses two sequential mutations from action #92

Description

@davidoort

Bug Description

rag.add() intermittently throws "Namespace <id> not found" on the convex-local-backend (OSS binary). The error occurs because add() calls two sequential component mutations from within an action:

  1. ctx.runMutation(this.component.namespaces.getOrCreate, ...) -- creates namespace, returns namespaceId
  2. ctx.runMutation(this.component.entries.add, { entry: { namespaceId, ... } }) -- reads namespace via ctx.db.get(namespaceId) → intermittently returns null

The Convex best practices docs warn: "Multiple runQuery/runMutations execute in separate transactions and aren't guaranteed to be consistent with each other."

Reproduction

The bug is timing/load-sensitive and manifests ~50% of the time when:

  • Running on convex-local-backend (not observed on cloud)
  • Calling rag.add() in a loop (e.g., 200+ entries) from a single action
  • System is under load (e.g., parallel test backends, concurrent deployments)

Simplified progressive isolation tests (20-200 iterations) do NOT reproduce the bug. It only triggers under real-world conditions with system load.

Minimal reproduction path

// In an internalAction:
for (const entry of CATALOG_ENTRIES) {  // ~200 entries
    await rag.add(ctx, {
        namespace: "global",
        key: entry.slug,
        text: entry.description,
    });
}

The first rag.add() call creates the namespace via getOrCreate, then the subsequent entries.add mutation fails to see it.

Error

Uncaught Error: Namespace jd79r35yh30qxy84rxpcnt7k1984b0pq not found
    at assert (convex-helpers/index.js:113:0)
    at handler (@convex-dev/rag/src/component/entries.ts:212:4)

Specifically, entries.ts:210-211:

const namespace = await ctx.db.get(namespaceId);
assert(namespace, `Namespace ${namespaceId} not found`);

Investigation Findings

  1. createFunctionHandle is NOT involved -- the add() path (without onComplete) does not call it before entries.add
  2. The error is ctx.db.get(namespaceId) returning null in the entries.add mutation for a namespace just created by getOrCreate in the previous mutation
  3. Both mutations are in the same component, called sequentially from the same action
  4. The issue does not occur on the Convex cloud backend

Suggested Fix

Combine getOrCreateNamespace and entries.add into a single component mutation to avoid the cross-transaction visibility issue. This would align with Convex's best practice of batching runMutation calls.

Versions

  • @convex-dev/rag: 0.7.2
  • convex: 1.34.1
  • convex-local-backend: latest (downloaded from GitHub releases)
  • convex-helpers: 0.1.114

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