From 528c9558bac8620d00c0b6143692a69fa329da40 Mon Sep 17 00:00:00 2001 From: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com> Date: Sat, 13 Jun 2026 17:41:42 +0500 Subject: [PATCH] fix(objectql): seed reference resolution falls back to matching by id MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SeedLoaderService.resolveFromDatabase only matched a reference value against the target's natural-key field. A seed that wires a lookup to a REAL existing record by its internal id — e.g. a people field (approver/applicant → user) pointed at the current user — dangled to null when that id is not a UUID/ObjectId (so the caller's `looksLikeInternalId` guard did not short-circuit) and is not the target's natural key. Add an id fallback: when the natural-key lookup finds nothing, try resolving the value as the target's `id`. Safe — an id either exists or it doesn't, so there's no risk of a false natural-key match; and it's tenant-scoped like the primary lookup. Co-Authored-By: Claude Opus 4.8 (1M context) --- packages/objectql/src/seed-loader.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/packages/objectql/src/seed-loader.ts b/packages/objectql/src/seed-loader.ts index 06bad9b2db..420dfbbbd9 100644 --- a/packages/objectql/src/seed-loader.ts +++ b/packages/objectql/src/seed-loader.ts @@ -448,6 +448,25 @@ export class SeedLoaderService implements ISeedLoaderService { if (records && records.length > 0) { return String(records[0].id || records[0]._id); } + // Fallback: the value may already be the target's internal id rather than + // its natural key — a seed that wires a lookup to a real existing record + // (e.g. a people field → the current user, whose id is not a UUID/ObjectId + // so `looksLikeInternalId` did not short-circuit). Resolving by id lets a + // valid id resolve instead of dangling null, with no risk of a false + // natural-key match (an id either exists or it does not). + if (targetField !== 'id') { + const byId: Record = { id: value }; + if (organizationId) byId.organization_id = organizationId; + const idMatch = await this.engine.find(targetObject, { + where: byId, + fields: ['id'], + limit: 1, + context: { isSystem: true }, + } as any); + if (idMatch && idMatch.length > 0) { + return String(idMatch[0].id || idMatch[0]._id); + } + } } catch { // Target object may not exist yet }