Skip to content

(via EnkiP): fix(workflow-executor): restore field names in fetchXToOneCandidate befo#1611

Open
macroscopeapp[bot] wants to merge 3 commits into
feat/prd-214-server-step-mapperfrom
macroscope/fix/load-related-record
Open

(via EnkiP): fix(workflow-executor): restore field names in fetchXToOneCandidate befo#1611
macroscopeapp[bot] wants to merge 3 commits into
feat/prd-214-server-step-mapperfrom
macroscope/fix/load-related-record

Conversation

@macroscopeapp
Copy link
Copy Markdown

@macroscopeapp macroscopeapp Bot commented May 29, 2026

Summary

Fixes an issue where relations with underscores in their names (e.g., customer_order) would trigger spurious RelatedRecordNotFoundError when accessing them in the workflow executor.

Changes

  • Added a call to restoreFieldNames in fetchXToOneCandidate after retrieving the parent record from agentPort.getRecord
  • This converts camelCase keys (returned by agent-client) back to their original format (e.g., snake_case), ensuring relation fields are correctly accessed

Root Cause

The agent-client returns records with camelCase keys, but relation lookups were using the original field names (which may contain underscores). Without restoring the field names first, the relation key wouldn't match and the lookup would fail.

Note

Macroscope: Fix It For Me

  • This PR originated from this comment in fix: load related record #1610.
  • Since auto-merge is on, Macroscope will merge this PR after waiting for checks to pass.
  • If you'd rather not wait, you can always merge this yourself but no further action from you is currently needed.
  • You can also @mention Macroscope in this PR to request further changes.

Activity

Currently: Not merged: unstable

Previously
  • Waiting on checks
  • Action failed: Lint, Build, Test and Doc
  • Waiting on checks
  • Pushed eb2e978

Note

Fix field name restoration in fetchXToOneCandidate for BelongsTo/HasOne relations

  • Rewrites xToOne (BelongsTo/HasOne) candidate lookup to project the related primary key and optional reference field directly from the parent record via agentPort.getRecord, rather than querying via getRelatedData.
  • Introduces fetchXToOneCandidate and fetchRelatedData methods in load-related-record-step-executor.ts to restore original field names and build correct recordId arrays using the related schema's declared primary key fields.
  • Changes LoadRelatedRecordPendingData to use availableFields, suggestedField, availableRecordIds (with optional referenceFieldValue), and suggestedRecord instead of the previous flat displayName/name/selectedRecordId shape.
  • Adds a field-preview patch mode in pending-data-validators.ts where only fieldDisplayName is provided (no userConfirmed), triggering a candidate refresh without confirmation.
  • Simplifies AgentClientAgentPort.getRelatedData to return raw rows (Record<string, unknown>[]) and moves field name restoration responsibility to the executor.
  • Risk: LoadRelatedRecordPendingData shape is a breaking change for any clients reading or writing that structure.
📊 Macroscope summarized eb2e978. 6 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted

🗂️ Filtered Issues

No issues evaluated.

@Scra3 Scra3 force-pushed the fix/load-related-record branch 3 times, most recently from 2799340 to 7b222de Compare June 2, 2026 13:57
Base automatically changed from fix/load-related-record to feat/prd-214-server-step-mapper June 3, 2026 09:46
Comment on lines +317 to +318
if (!packedId) {
throw new RelatedRecordNotFoundError(target.selectedRecordRef.collectionName, target.name);
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium executors/load-related-record-step-executor.ts:317

In fetchXToOneCandidate, the nested relation object's field names are not restored using the related collection's schema, causing extractReferenceFieldValue to return null for reference fields with non-camelCase names (e.g., full_name). At line 316-319, restoreFieldNames is called with sourceSchema.fields (the parent collection), but the nested relation object contains fields from the related collection. When the agent's JSON:API serializer returns fullName (camelCased), but referenceField is full_name, the lookup relation[referenceField] returns undefined. Consider using relatedSchema.fields for restoration before extracting the reference field value.

-    const relation = restoredValues[target.name] as Record<string, unknown> | null | undefined;
-    const packedId = relation?.id as string | undefined;
+    const relation = restoredValues[target.name] as Record<string, unknown> | null | undefined;
+    const relatedSchema = await this.getCollectionSchema(target.relatedCollectionName);
+    const restoredRelation = relation
+      ? restoreFieldNames(
+          relation,
+          relatedSchema.fields.map(f => f.fieldName),
+        )
+      : null;
+    const packedId = restoredRelation?.id as string | undefined;
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file packages/workflow-executor/src/executors/load-related-record-step-executor.ts around lines 317-318:

In `fetchXToOneCandidate`, the nested relation object's field names are not restored using the related collection's schema, causing `extractReferenceFieldValue` to return `null` for reference fields with non-camelCase names (e.g., `full_name`). At line 316-319, `restoreFieldNames` is called with `sourceSchema.fields` (the parent collection), but the nested `relation` object contains fields from the related collection. When the agent's JSON:API serializer returns `fullName` (camelCased), but `referenceField` is `full_name`, the lookup `relation[referenceField]` returns `undefined`. Consider using `relatedSchema.fields` for restoration before extracting the reference field value.

Evidence trail:
packages/workflow-executor/src/executors/load-related-record-step-executor.ts lines 279-327 (fetchXToOneCandidate), lines 308-312 (restoreFieldNames with sourceSchema.fields), line 314 (nested relation extraction), lines 323-324 (extractReferenceFieldValue with referenceField from relatedSchema).
packages/workflow-executor/src/adapters/agent-client-agent-port.ts lines 28-42 (restoreFieldNames implementation: only operates on top-level keys), line 90 (getRecord's restoreFieldNames with projection fields).
packages/workflow-executor/src/executors/load-related-record-step-executor.ts lines 482-486 (fetchRelatedData correctly uses relatedSchema.fields for restoreFieldNames — the correct pattern).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant