get-convex / get-convex/rag

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

Open
#92 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
36
Forks
13
Avg merge
4h 2m
Merged PRs (30d)
2

Description

## Bug Description

`rag.add()` intermittently throws "Namespace \ 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

```typescript
// 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`:
```typescript
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

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.