{"record":{"id":"ac3bd13bd644224a","repo":"windmill-labs/windmill","slug":"no-resource-metadata-file-found-for-fileset-resour","errorCode":null,"errorMessage":"No resource metadata file found for fileset resource: ${changePath}","messagePattern":"No resource metadata file found for fileset resource: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/src/commands/sync/sync.ts","lineNumber":1062,"sourceCode":"  // `<base>.fileset/` while its metadata file carries the workspace suffix.\n  // The suffixed file is this workspace's authoritative metadata, so it must\n  // win over a base file that coexists with it.\n  if (wsName) {\n    candidates.unshift(\n      toWorkspaceSpecificPath(basePath + \".resource.json\", wsName),\n      toWorkspaceSpecificPath(basePath + \".resource.yaml\", wsName),\n    );\n  }\n\n  for (const candidate of candidates) {\n    try {\n      const s = await stat(candidate);\n      if (s.isFile()) return candidate;\n    } catch {\n      // not found, try next\n    }\n  }\n  throw new Error(\n    `No resource metadata file found for fileset resource: ${changePath}`,\n  );\n}\n\ntype FilesetPushResult =\n  | { status: \"pushed\"; resourceFilePath: string }\n  | { status: \"already-synced\"; resourceFilePath: string }\n  | { status: \"parent-missing\" };\n\nasync function pushFilesetParentResource(\n  childPath: string,\n  workspaceId: string,\n  alreadySynced: string[],\n  cachedWsName: string | null,\n  specificItems?: SpecificItemsConfig,\n): Promise<FilesetPushResult> {\n  let resourceFilePath: string;\n  try {","sourceCodeStart":1044,"sourceCodeEnd":1080,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/cli/src/commands/sync/sync.ts#L1044-L1080","documentation":"findFilesetResourceFile() looks for the parent resource metadata file of a `.fileset/` folder, checking workspace-specific suffixed files first (when a workspace name is given) then the base `.resource.json` / `.resource.yaml` candidates. It throws when the `.fileset/` folder exists on disk but none of the expected metadata files exist beside it, meaning the fileset is orphaned.","triggerScenarios":"A `.fileset/` directory exists (or a change is reported inside one) but `<base>.resource.json`, `<base>.resource.yaml`, and their workspace-suffixed variants are all missing — e.g. the metadata file was deleted/renamed, or the folder was renamed without renaming the metadata.","commonSituations":"Manually deleting or renaming the `.resource.json`/`.resource.yaml` while keeping the `.fileset/` folder; git merge/checkout leaving the folder but not the metadata; workspace-specific metadata expected under a suffixed name that was never pulled; partial restore from backup.","solutions":["Restore or re-create the metadata file `<base>.resource.json` (or `.yaml`) next to the `.fileset/` folder — easiest via `wmill sync pull` or re-pulling that single resource","If the resource is intentionally deleted, delete the whole `<base>.fileset/` folder so no orphan child changes remain","Check whether the metadata lives under a workspace-suffixed name that does not match the workspace you are syncing; align the suffix or pass the correct wsName","Check git status — a pending rename or unmerged path may have removed the metadata; resolve the merge properly"],"exampleFix":"// before (orphaned)\nu/my_resource.fileset/data.json   // no u/my_resource.resource.json\n// after\nwmill resource pull u/my_resource  # regenerates u/my_resource.resource.json beside the .fileset folder","handlingStrategy":"validation","validationCode":"import { statSync } from 'fs';\nconst base = changePath.slice(0, changePath.indexOf('.fileset'));\nconst ok = ['.resource.json', '.resource.yaml'].some(ext => {\n  try { return statSync(base + ext).isFile(); } catch { return false; }\n});\nif (!ok) console.error(`orphaned fileset: ${changePath}`);","typeGuard":"function hasFilesetMetadata(basePath: string): boolean {\n  return ['.resource.json', '.resource.yaml'].some(ext => existsSync(basePath + ext));\n}","tryCatchPattern":"try {\n  const meta = await findFilesetResourceFile(childPath, ws);\n} catch {\n  // treat as parent-missing: skip push or re-pull the resource\n}","preventionTips":["Never delete the .resource.json/.resource.yaml while keeping the .fileset/ folder — delete both together","Run `wmill sync pull` after manual filesystem surgery on resources","Watch for renames that move the folder but not the metadata (git mv the whole pair)"],"tags":["cli","sync","fileset","missing-file"],"backgroundTag":"missing-resource-metadata","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}