windmill-labs/windmill · error
Cannot get content of folder
Error message
Cannot get content of folder
What it means
The internal folder node of the zip-based sync FS (the root '.' entry built by _internal_folder) also stubs getContentText() with 'Cannot get content of folder'. It is thrown when someone tries to read the text of the virtual root or any synthesized folder node rather than a real archived file.
Source
Thrown at cli/src/commands/sync/sync.ts:1901
isDirectory: true,
path: p,
async *getChildren(): AsyncIterable<DynFSElement> {
for (const filename in zip.files) {
const file = zip.files[filename];
const totalPath = path.join(p, filename);
if (file.dir) {
const e = zip.folder(file.name)!;
yield _internal_folder(totalPath, e);
} else {
const fs = await _internal_file(totalPath, file);
for (const f of fs) {
yield f;
}
}
}
},
async getContentText(): Promise<string> {
throw new Error("Cannot get content of folder");
},
};
}
return _internal_folder("." + SEP, zip);
}
/**
* Directories no walk over a workspace ever descends, whatever the sync scope:
* dependency trees, and the dot-directories that hold tooling state and
* fixtures. Exported because a second walk that disagrees with this one reads
* files sync will never see, and draws conclusions from them.
*/
export function isNeverWalkedDir(dirName: string | undefined): boolean {
return (
dirName === "node_modules" || (dirName !== undefined && dirName.startsWith("."))
);
}
View on GitHub (pinned to e474e8803c)
Solutions
- Start from getChildren() on the root and only call getContentText() on leaf file entries
- Add an isDirectory check before any content read
- If you need a text dump of the archive, iterate files individually rather than reading folders
Example fix
// before
const all = await root.getContentText();
// after
for (const child of await root.getChildren()) {
if (!child.isDirectory) console.log(child.path, await child.getContentText());
} Defensive patterns
Strategy: try-catch
Validate before calling
if (node.path === '.' + SEP || node.isDirectory) {
throw new Error('use getChildren() on folders');
}
const text = await node.getContentText(); Type guard
function isRootFolder(e: DynFSElement): boolean {
return e.isDirectory && e.path === '.' + path.sep;
} Try / catch
try {
const text = await node.getContentText();
} catch (e) {
if (e.message === 'Cannot get content of folder') {
// it's the root/virtual folder — iterate children instead
} else throw e;
} Prevention
- Treat the zip root as a container only — always start with getChildren()
- Never assume a single node holds the whole archive as text
- Add isDirectory checks in any generic tree walker
When it happens
Trigger: Calling getContentText() on the root element returned by ZipFSElement/_internal_folder, or on any synthesized folder while walking the zip tree; treating the whole zip tree as a single text blob.
Common situations: Scripts that dump every entry's content starting from the root; confusing the folder abstraction (getChildren) with file reading; debugging code that assumed the root had content.
Related errors
- Cannot get content of directory
- Workspace folder not found, are you in the right directory?
- Content of raw app file ${filePath} is not a string
- Error reading dir: ${localP}, ${e}
- Found ${collisions.length} path(s) that differ only by lette
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/edd66884ba8ed297.
Report an issue: GitHub.