{"record":{"id":"14d3003ec952729d","repo":"windmill-labs/windmill","slug":"resource-remotepath-uses-inline-fileset-dir","errorCode":null,"errorMessage":"Resource ${remotePath} uses '!inline_fileset ${dirPath}', but a fileset directory must live next to its resource file, at '${expected}'. Move the directory there (e.g. 'git mv ${pointer} ${expected}') and update the '!inline_fileset' value to match.","messagePattern":"Resource (.+?) uses '!inline_fileset (.+?)', but a fileset directory must live next to its resource file, at '(.+?)'\\. Move the directory there \\(e\\.g\\. 'git mv (.+?) (.+?)'\\) and update the '!inline_fileset' value to match\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/src/commands/resource/resource.ts","lineNumber":66,"sourceCode":"\n/**\n * A fileset directory must live at the server-canonical location\n * `<resource path>.fileset` — that is the only layout the sync diff engine\n * can round-trip (remote state is always rendered there, including for\n * workspace-specific resources). Any other pointer breaks change detection:\n * children are planned as full delete/re-add churn and adds under the custom\n * directory are dropped, which manifests as erased or stale fileset content.\n */\nexport function validateFilesetPointer(\n  dirPath: string,\n  remotePath: string,\n): void {\n  const normalize = (p: string) =>\n    p.replaceAll(\"\\\\\", \"/\").replace(/\\/+$/, \"\");\n  const pointer = normalize(dirPath);\n  const expected = normalize(remotePath.replaceAll(SEP, \"/\")) + \".fileset\";\n  if (pointer !== expected) {\n    throw new Error(\n      `Resource ${remotePath.replaceAll(SEP, \"/\")} uses '!inline_fileset ${dirPath}', ` +\n        `but a fileset directory must live next to its resource file, at '${expected}'. ` +\n        `Move the directory there (e.g. 'git mv ${pointer} ${expected}') and update the ` +\n        `'!inline_fileset' value to match.`,\n    );\n  }\n}\n\nexport async function pushResource(\n  workspace: string,\n  remotePath: string,\n  resource: ResourceFile | Resource | undefined,\n  localResource: ResourceFile,\n  originalLocalPath?: string,\n  wsSpecific?: boolean,\n  // Sync pushes reject non-canonical fileset pointers (the diff engine can\n  // only round-trip the canonical layout); the standalone `resource push`\n  // command pushes a single explicit file, where any pointer is fine.","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/cli/src/commands/resource/resource.ts#L48-L84","documentation":"This error comes from the Windmill CLI when validating an '!inline_fileset' pointer in a resource YAML file. The CLI expects the fileset directory (the folder holding the resource's inline content) to sit directly next to the resource file and be named '<resource-filename>.fileset'. If the '!inline_fileset' value names a directory at any other path, validateFilesetPointer throws so the resource is not pushed with its content silently detached.","triggerScenarios":"Calling `wmill resource push` (or resolveInlineContent during push) on a `*.resource.yaml` file whose value is `!inline_fileset <dirPath>` where normalize(dirPath) !== normalize(remotePath with SEP->'/') + '.fileset'. E.g. resource file 'myres.resource.yaml' containing '!inline_fileset ./data' instead of '!inline_fileset myres.fileset'.","commonSituations":"Renaming or moving the resource file without renaming/moving the fileset directory; hand-writing the pointer with a custom folder name; moving files between directories with `mv` while forgetting the sibling directory; Windows path separators (backslashes) in the pointer; trailing slash in the pointer value.","solutions":["Rename/move the fileset directory next to the resource file so it is exactly '<resource-filename>.fileset', e.g. `git mv ./data myres.fileset`","Update the '!inline_fileset' value in the resource YAML to 'myres.fileset' to match the new directory name","If the content should just be inline instead, replace the '!inline_fileset' directive with the literal resource value"],"exampleFix":"// before: myres.resource.yaml\nvalue: !inline_fileset ./data\n// after (after `git mv ./data myres.fileset`)\nvalue: !inline_fileset myres.fileset","handlingStrategy":"validation","validationCode":"import { statSync } from 'fs';\nimport { basename, join, dirname } from 'path';\n\nfunction assertFilesetPointer(resourceFilePath: string, pointer: string) {\n  const expected = basename(resourceFilePath).replace(/\\.resource\\.yaml$/, '') + '.fileset';\n  const normalized = pointer.replaceAll('\\\\', '/').replace(/\\/+$/, '');\n  if (normalized !== expected) {\n    throw new Error(\n      `'!inline_fileset ${pointer}' should be '${expected}' next to ${resourceFilePath}`\n    );\n  }\n  statSync(join(dirname(resourceFilePath), expected)); // dir must exist\n}","typeGuard":null,"tryCatchPattern":"try {\n  await cli.resource.push(remotePath, resourceFile);\n} catch (e) {\n  if ((e as Error).message.includes(\"!inline_fileset\") && e.message.includes(\"must live next to its resource file\")) {\n    // fix pointer: rename dir to <name>.fileset and update YAML, then retry\n  } else throw e;\n}","preventionTips":["Always name the fileset dir '<resource-filename>.fileset' in the same folder as the resource YAML","Use `git mv` so renames keep history when relocating resources and their filesets together","Add a pre-commit/pre-push lint that parses `.resource.yaml` files and checks pointer paths","Never hand-write backslashes or trailing slashes in the pointer value"],"tags":["cli","windmill","fileset","path-validation"],"backgroundTag":"fileset-pointer-misplaced","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"}