Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 2 additions & 5 deletions app/models/guilds.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,11 @@ export const fetchSettings = async <T extends keyof typeof SETTINGS>(
// old/bad use of jsonb for storing settings. The type is guaranteed here
// not by the codegen
.select<DB, "guilds", SettingsRecord>((eb) =>
keys.map((k) => eb.ref("settings", "->").key(k).as(k)),
keys.map((k) => eb.ref("settings", "->>").key(k).as(k)),
)
.where("id", "=", guildId)
// This cast is also evidence of the pattern being broken
.executeTakeFirstOrThrow(),
) as [T, string][];
return Object.fromEntries(result.map(([k, v]) => [k, JSON.parse(v)])) as Pick<
SettingsRecord,
T
>;
return Object.fromEntries(result) as Pick<SettingsRecord, T>;
};
34 changes: 34 additions & 0 deletions notes/2026-01-23_1_json-extraction-fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# JSON Extraction Fix in fetchSettings

## Problem

The `fetchSettings` function was experiencing JSON parse errors: `"[object Object]" is not valid JSON`.

## Root Cause

The function used SQLite's `->` operator for JSON extraction, combined with Kysely's `ParseJSONResultsPlugin`:

- `->` operator returns JSON text (strings include quotes: `"925847644318879754"`)
- `ParseJSONResultsPlugin` only parses values starting with `{` or `[`
- String values weren't parsed by the plugin, so `JSON.parse()` was needed
- Non-string values (objects, arrays) WERE parsed by the plugin, causing double-parsing errors

## Solution

Changed from `->` to `->>` operator:

```typescript
// Before: returns JSON text, requires JSON.parse for strings
eb.ref("settings", "->").key(k).as(k)

// After: returns extracted value directly, no parsing needed
eb.ref("settings", "->>").key(k).as(k)
```

SQLite operators:
- `->` returns the value as JSON text
- `->>` returns the value as SQL text/number (extracted value)

## Files Modified

- `app/models/guilds.server.ts` - Changed `->` to `->>` and removed `JSON.parse()`