diff --git a/apps/client/src/features/base/hooks/use-base-table.ts b/apps/client/src/features/base/hooks/use-base-table.ts index 227663fa..f09a71e0 100644 --- a/apps/client/src/features/base/hooks/use-base-table.ts +++ b/apps/client/src/features/base/hooks/use-base-table.ts @@ -181,6 +181,12 @@ export function buildViewConfigFromTable( base: ViewConfig | undefined, overrides: Partial = {}, ): ViewConfig { + // Guard against corrupted persisted configs — if `base` ever comes + // back as something other than a plain object (e.g. a jsonb-stored + // string `"{}"` from a buggy seed), spreading it would iterate its + // characters into keys `0`, `1`, … and poison the config forever. + const safeBase = + base && typeof base === "object" && !Array.isArray(base) ? base : {}; const state = table.getState(); const sorts = state.sorting.map((s) => ({ @@ -200,7 +206,7 @@ export function buildViewConfigFromTable( .map(([id]) => id); return { - ...base, + ...safeBase, sorts, propertyWidths, propertyOrder, diff --git a/apps/server/src/scripts/seed-base-rows.ts b/apps/server/src/scripts/seed-base-rows.ts index 5b485920..5bd96d42 100644 --- a/apps/server/src/scripts/seed-base-rows.ts +++ b/apps/server/src/scripts/seed-base-rows.ts @@ -196,7 +196,7 @@ async function createBase(workspaceId: string, spaceId: string, creatorId: strin name: def.name, type: def.type, position: propPosition, - type_options: def.typeOptions ? JSON.stringify(def.typeOptions) : null, + type_options: def.typeOptions ?? null, is_primary: def.isPrimary ?? false, workspace_id: workspaceId, created_at: new Date(), @@ -219,7 +219,7 @@ async function createBase(workspaceId: string, spaceId: string, creatorId: strin name: 'Table View 1', type: 'table', position: generateJitteredKeyBetween(null, null), - config: JSON.stringify({}), + config: {}, workspace_id: workspaceId, creator_id: creatorId, created_at: new Date(),