Skip to content

fix(PROD-2277): models-only sync crashes in push with ENOENT on galleries folder#173

Open
5PK wants to merge 2 commits into
mainfrom
fix/PROD-2277-models-only-galleries-enoent
Open

fix(PROD-2277): models-only sync crashes in push with ENOENT on galleries folder#173
5PK wants to merge 2 commits into
mainfrom
fix/PROD-2277-models-only-galleries-enoent

Conversation

@5PK

@5PK 5PK commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

Summary

A models-only sync — sync --models="X" (and the same code path for --elements="Models") — crashes in the push phase on a clean machine:

✗ Sync completed with errors
  •  sync: guid-orchestration: ENOENT: no such file or directory,
     scandir 'agility-files/<sourceGuid>/galleries'

This is a regression from PROD-2215 (#166). That fix correctly makes a models-only scope download only model definitions (skipping assets, galleries, content) — but the push-side loader still reads the galleries folder unconditionally, and that folder is now never created.

Root cause

  • guid-data-loader.ts (~L85, ~L400) calls getGalleriesFromFileSystem() unconditionally during push.
  • get-galleries.tsfileOperations.getFolderContents()fs.readdirSync(folder) with no existence guard (fileOperations.ts ~L273).
  • Pre-PROD-2215 the downloader fetched galleries regardless of scope, which created agility-files/<guid>/galleries (even empty), so readdirSync returned []. PROD-2215 stopped creating it for models-only runs → ENOENT.

Fix

getFolderContents now creates the folder on demand and returns [] when absent, matching the guards already in readJsonFilesFromFolder/listFilesInFolder:

getFolderContents(folder: string) {
  if (!fs.existsSync(folder)) {
    fs.mkdirSync(folder, { recursive: true });
    return [];
  }
  return fs.readdirSync(folder);
}

Creating the folder (rather than only guarding the read) also restores the consistent instance-folder scaffolding downstream steps assume. All four callers (get-galleries, gallery-mapper, mapping-reader ×2) want "list files, empty if none", so auto-create is safe.

Testing

  • Clean sync --sourceGuid=… --targetGuid=… --models="AssetTest" (no local agility-files, no workaround) → ✓ Sync completed successfully; galleries/assets correctly skipped in push; folders auto-created.
  • Regression test added in fileOperations.test.ts (missing folder → returns [] and folder is created).
  • Affected suites green (fileOperations / gallery-pusher / gallery-mapper / mapping-reader); full suite 1685 tests passing.

Jira: PROD-2277

🤖 Generated with Claude Code

5PK and others added 2 commits July 6, 2026 11:38
…nc doesn't ENOENT

A models-only sync (--models / --elements="Models") skips downloading galleries
(the PROD-2215 optimization), so agility-files/<guid>/galleries is never created.
But the push-side loader still reads it unconditionally:
guid-data-loader -> getGalleriesFromFileSystem -> fileOperations.getFolderContents
-> fs.readdirSync, which threw ENOENT and aborted the whole sync.

Make getFolderContents create the folder and return [] when it is absent, matching
the guards already present in readJsonFilesFromFolder/listFilesInFolder. Creating
the folder (not just guarding the read) also restores the instance-folder
scaffolding downstream steps assume. All four callers want "list files, empty if
none", so auto-create is safe. Adds a regression test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ing folder

This test previously asserted the old buggy behavior — that a missing galleries
folder throws (the ENOENT that crashed a models-only sync). Update it to assert
the fixed behavior: returns [], creates the folder, and does not throw.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@5PK 5PK requested a review from jules-exel July 6, 2026 19:23
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