Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions .changeset/prevent-custom-getkey-with-joins.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
"@tanstack/db": patch
---

Improve error messages for custom getKey with joined queries

Enhanced `DuplicateKeySyncError` to provide context-aware guidance when duplicate keys occur with custom `getKey` and joined queries.

**The Issue:**

When using custom `getKey` with joins, duplicate keys can occur if the join produces multiple rows with the same key value. This is valid for 1:1 relationships but problematic for 1:many relationships, and the previous error message didn't explain what went wrong or how to fix it.

**What's New:**

When a duplicate key error occurs in a live query collection that uses both custom `getKey` and joins, the error message now:

- Explains that joined queries can produce multiple rows with the same key
- Suggests using a composite key in your `getKey` function
- Provides concrete examples of solutions
- Helps distinguish between correctly structured 1:1 joins vs problematic 1:many joins

**Example:**

```typescript
// ✅ Valid - 1:1 relationship with unique keys
const userProfiles = createLiveQueryCollection({
query: (q) =>
q
.from({ profile: profiles })
.join({ user: users }, ({ profile, user }) =>
eq(profile.userId, user.id)
),
getKey: (profile) => profile.id, // Each profile has unique ID
})
```

```typescript
// ⚠️ Problematic - 1:many relationship with duplicate keys
const userComments = createLiveQueryCollection({
query: (q) =>
q
.from({ user: users })
.join({ comment: comments }, ({ user, comment }) =>
eq(user.id, comment.userId)
),
getKey: (item) => item.userId, // Multiple comments share same userId!
})

// Enhanced error message:
// "Cannot insert document with key "user1" from sync because it already exists.
// This collection uses a custom getKey with joined queries. Joined queries can
// produce multiple rows with the same key when relationships are not 1:1.
// Consider: (1) using a composite key in your getKey function (e.g., `${item.key1}-${item.key2}`),
// (2) ensuring your join produces unique rows per key, or (3) removing the
// custom getKey to use the default composite key behavior."
```
4 changes: 2 additions & 2 deletions docs/reference/classes/AggregateFunctionNotInSelectError.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ title: AggregateFunctionNotInSelectError

# Class: AggregateFunctionNotInSelectError

Defined in: [packages/db/src/errors.ts:531](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L531)
Defined in: [packages/db/src/errors.ts:547](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L547)

## Extends

Expand All @@ -19,7 +19,7 @@ Defined in: [packages/db/src/errors.ts:531](https://github.com/TanStack/db/blob/
new AggregateFunctionNotInSelectError(functionName): AggregateFunctionNotInSelectError;
```

Defined in: [packages/db/src/errors.ts:532](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L532)
Defined in: [packages/db/src/errors.ts:548](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L548)

#### Parameters

Expand Down
4 changes: 2 additions & 2 deletions docs/reference/classes/AggregateNotSupportedError.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ title: AggregateNotSupportedError

# Class: AggregateNotSupportedError

Defined in: [packages/db/src/errors.ts:647](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L647)
Defined in: [packages/db/src/errors.ts:663](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L663)

Error thrown when aggregate expressions are used outside of a GROUP BY context.

Expand All @@ -21,7 +21,7 @@ Error thrown when aggregate expressions are used outside of a GROUP BY context.
new AggregateNotSupportedError(): AggregateNotSupportedError;
```

Defined in: [packages/db/src/errors.ts:648](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L648)
Defined in: [packages/db/src/errors.ts:664](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L664)

#### Returns

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ title: CannotCombineEmptyExpressionListError

# Class: CannotCombineEmptyExpressionListError

Defined in: [packages/db/src/errors.ts:610](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L610)
Defined in: [packages/db/src/errors.ts:626](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L626)

## Extends

Expand All @@ -19,7 +19,7 @@ Defined in: [packages/db/src/errors.ts:610](https://github.com/TanStack/db/blob/
new CannotCombineEmptyExpressionListError(): CannotCombineEmptyExpressionListError;
```

Defined in: [packages/db/src/errors.ts:611](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L611)
Defined in: [packages/db/src/errors.ts:627](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L627)

#### Returns

Expand Down
4 changes: 2 additions & 2 deletions docs/reference/classes/CollectionInputNotFoundError.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ title: CollectionInputNotFoundError

# Class: CollectionInputNotFoundError

Defined in: [packages/db/src/errors.ts:391](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L391)
Defined in: [packages/db/src/errors.ts:407](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L407)

Error thrown when a collection input stream is not found during query compilation.
In self-joins, each alias (e.g., 'employee', 'manager') requires its own input stream.
Expand All @@ -25,7 +25,7 @@ new CollectionInputNotFoundError(
availableKeys?): CollectionInputNotFoundError;
```

Defined in: [packages/db/src/errors.ts:392](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L392)
Defined in: [packages/db/src/errors.ts:408](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L408)

#### Parameters

Expand Down
4 changes: 2 additions & 2 deletions docs/reference/classes/DeleteKeyNotFoundError.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ title: DeleteKeyNotFoundError

# Class: DeleteKeyNotFoundError

Defined in: [packages/db/src/errors.ts:204](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L204)
Defined in: [packages/db/src/errors.ts:220](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L220)

## Extends

Expand All @@ -19,7 +19,7 @@ Defined in: [packages/db/src/errors.ts:204](https://github.com/TanStack/db/blob/
new DeleteKeyNotFoundError(key): DeleteKeyNotFoundError;
```

Defined in: [packages/db/src/errors.ts:205](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L205)
Defined in: [packages/db/src/errors.ts:221](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L221)

#### Parameters

Expand Down
4 changes: 2 additions & 2 deletions docs/reference/classes/DistinctRequiresSelectError.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ title: DistinctRequiresSelectError

# Class: DistinctRequiresSelectError

Defined in: [packages/db/src/errors.ts:367](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L367)
Defined in: [packages/db/src/errors.ts:383](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L383)

## Extends

Expand All @@ -19,7 +19,7 @@ Defined in: [packages/db/src/errors.ts:367](https://github.com/TanStack/db/blob/
new DistinctRequiresSelectError(): DistinctRequiresSelectError;
```

Defined in: [packages/db/src/errors.ts:368](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L368)
Defined in: [packages/db/src/errors.ts:384](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L384)

#### Returns

Expand Down
4 changes: 2 additions & 2 deletions docs/reference/classes/DuplicateAliasInSubqueryError.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ title: DuplicateAliasInSubqueryError

# Class: DuplicateAliasInSubqueryError

Defined in: [packages/db/src/errors.ts:412](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L412)
Defined in: [packages/db/src/errors.ts:428](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L428)

Error thrown when a subquery uses the same alias as its parent query.
This causes issues because parent and subquery would share the same input streams,
Expand All @@ -23,7 +23,7 @@ leading to empty results or incorrect data (aggregation cross-leaking).
new DuplicateAliasInSubqueryError(alias, parentAliases): DuplicateAliasInSubqueryError;
```

Defined in: [packages/db/src/errors.ts:413](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L413)
Defined in: [packages/db/src/errors.ts:429](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L429)

#### Parameters

Expand Down
15 changes: 14 additions & 1 deletion docs/reference/classes/DuplicateKeySyncError.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ Defined in: [packages/db/src/errors.ts:162](https://github.com/TanStack/db/blob/
### Constructor

```ts
new DuplicateKeySyncError(key, collectionId): DuplicateKeySyncError;
new DuplicateKeySyncError(
key,
collectionId,
options?): DuplicateKeySyncError;
```

Defined in: [packages/db/src/errors.ts:163](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L163)
Expand All @@ -31,6 +34,16 @@ Defined in: [packages/db/src/errors.ts:163](https://github.com/TanStack/db/blob/

`string`

##### options?

###### hasCustomGetKey?

`boolean`

###### hasJoins?

`boolean`

#### Returns

`DuplicateKeySyncError`
Expand Down
4 changes: 2 additions & 2 deletions docs/reference/classes/EmptyReferencePathError.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ title: EmptyReferencePathError

# Class: EmptyReferencePathError

Defined in: [packages/db/src/errors.ts:435](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L435)
Defined in: [packages/db/src/errors.ts:451](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L451)

## Extends

Expand All @@ -19,7 +19,7 @@ Defined in: [packages/db/src/errors.ts:435](https://github.com/TanStack/db/blob/
new EmptyReferencePathError(): EmptyReferencePathError;
```

Defined in: [packages/db/src/errors.ts:436](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L436)
Defined in: [packages/db/src/errors.ts:452](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L452)

#### Returns

Expand Down
4 changes: 2 additions & 2 deletions docs/reference/classes/GroupByError.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ title: GroupByError

# Class: GroupByError

Defined in: [packages/db/src/errors.ts:510](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L510)
Defined in: [packages/db/src/errors.ts:526](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L526)

## Extends

Expand All @@ -26,7 +26,7 @@ Defined in: [packages/db/src/errors.ts:510](https://github.com/TanStack/db/blob/
new GroupByError(message): GroupByError;
```

Defined in: [packages/db/src/errors.ts:511](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L511)
Defined in: [packages/db/src/errors.ts:527](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L527)

#### Parameters

Expand Down
4 changes: 2 additions & 2 deletions docs/reference/classes/HavingRequiresGroupByError.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ title: HavingRequiresGroupByError

# Class: HavingRequiresGroupByError

Defined in: [packages/db/src/errors.ts:373](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L373)
Defined in: [packages/db/src/errors.ts:389](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L389)

## Extends

Expand All @@ -19,7 +19,7 @@ Defined in: [packages/db/src/errors.ts:373](https://github.com/TanStack/db/blob/
new HavingRequiresGroupByError(): HavingRequiresGroupByError;
```

Defined in: [packages/db/src/errors.ts:374](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L374)
Defined in: [packages/db/src/errors.ts:390](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L390)

#### Returns

Expand Down
4 changes: 2 additions & 2 deletions docs/reference/classes/InvalidJoinCondition.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ title: InvalidJoinCondition

# Class: InvalidJoinCondition

Defined in: [packages/db/src/errors.ts:497](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L497)
Defined in: [packages/db/src/errors.ts:513](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L513)

## Extends

Expand All @@ -19,7 +19,7 @@ Defined in: [packages/db/src/errors.ts:497](https://github.com/TanStack/db/blob/
new InvalidJoinCondition(): InvalidJoinCondition;
```

Defined in: [packages/db/src/errors.ts:498](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L498)
Defined in: [packages/db/src/errors.ts:514](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L514)

#### Returns

Expand Down
4 changes: 2 additions & 2 deletions docs/reference/classes/InvalidJoinConditionLeftSourceError.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ title: InvalidJoinConditionLeftSourceError

# Class: InvalidJoinConditionLeftSourceError

Defined in: [packages/db/src/errors.ts:481](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L481)
Defined in: [packages/db/src/errors.ts:497](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L497)

## Extends

Expand All @@ -19,7 +19,7 @@ Defined in: [packages/db/src/errors.ts:481](https://github.com/TanStack/db/blob/
new InvalidJoinConditionLeftSourceError(sourceAlias): InvalidJoinConditionLeftSourceError;
```

Defined in: [packages/db/src/errors.ts:482](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L482)
Defined in: [packages/db/src/errors.ts:498](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L498)

#### Parameters

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ title: InvalidJoinConditionRightSourceError

# Class: InvalidJoinConditionRightSourceError

Defined in: [packages/db/src/errors.ts:489](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L489)
Defined in: [packages/db/src/errors.ts:505](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L505)

## Extends

Expand All @@ -19,7 +19,7 @@ Defined in: [packages/db/src/errors.ts:489](https://github.com/TanStack/db/blob/
new InvalidJoinConditionRightSourceError(sourceAlias): InvalidJoinConditionRightSourceError;
```

Defined in: [packages/db/src/errors.ts:490](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L490)
Defined in: [packages/db/src/errors.ts:506](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L506)

#### Parameters

Expand Down
4 changes: 2 additions & 2 deletions docs/reference/classes/InvalidJoinConditionSameSourceError.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ title: InvalidJoinConditionSameSourceError

# Class: InvalidJoinConditionSameSourceError

Defined in: [packages/db/src/errors.ts:467](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L467)
Defined in: [packages/db/src/errors.ts:483](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L483)

## Extends

Expand All @@ -19,7 +19,7 @@ Defined in: [packages/db/src/errors.ts:467](https://github.com/TanStack/db/blob/
new InvalidJoinConditionSameSourceError(sourceAlias): InvalidJoinConditionSameSourceError;
```

Defined in: [packages/db/src/errors.ts:468](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L468)
Defined in: [packages/db/src/errors.ts:484](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L484)

#### Parameters

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ title: InvalidJoinConditionSourceMismatchError

# Class: InvalidJoinConditionSourceMismatchError

Defined in: [packages/db/src/errors.ts:475](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L475)
Defined in: [packages/db/src/errors.ts:491](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L491)

## Extends

Expand All @@ -19,7 +19,7 @@ Defined in: [packages/db/src/errors.ts:475](https://github.com/TanStack/db/blob/
new InvalidJoinConditionSourceMismatchError(): InvalidJoinConditionSourceMismatchError;
```

Defined in: [packages/db/src/errors.ts:476](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L476)
Defined in: [packages/db/src/errors.ts:492](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L492)

#### Returns

Expand Down
4 changes: 2 additions & 2 deletions docs/reference/classes/InvalidSourceError.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ title: InvalidSourceError

# Class: InvalidSourceError

Defined in: [packages/db/src/errors.ts:339](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L339)
Defined in: [packages/db/src/errors.ts:355](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L355)

## Extends

Expand All @@ -19,7 +19,7 @@ Defined in: [packages/db/src/errors.ts:339](https://github.com/TanStack/db/blob/
new InvalidSourceError(alias): InvalidSourceError;
```

Defined in: [packages/db/src/errors.ts:340](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L340)
Defined in: [packages/db/src/errors.ts:356](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L356)

#### Parameters

Expand Down
4 changes: 2 additions & 2 deletions docs/reference/classes/InvalidStorageDataFormatError.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ title: InvalidStorageDataFormatError

# Class: InvalidStorageDataFormatError

Defined in: [packages/db/src/errors.ts:575](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L575)
Defined in: [packages/db/src/errors.ts:591](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L591)

## Extends

Expand All @@ -19,7 +19,7 @@ Defined in: [packages/db/src/errors.ts:575](https://github.com/TanStack/db/blob/
new InvalidStorageDataFormatError(storageKey, key): InvalidStorageDataFormatError;
```

Defined in: [packages/db/src/errors.ts:576](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L576)
Defined in: [packages/db/src/errors.ts:592](https://github.com/TanStack/db/blob/main/packages/db/src/errors.ts#L592)

#### Parameters

Expand Down
Loading
Loading