quasarframework/quasar · warning
render() - "${templatePath}" is a file instead of folder. Sk
Error message
render() - "${templatePath}" is a file instead of folder. Skipping... What it means
api.render() renders a folder of templates; this warning fires when the resolved path exists but is a regular FILE, not a directory. The call is skipped — use api.renderFile() for single files instead.
Source
Thrown at app-vite/lib/app-extension/api-classes/InstallAPI.js:256
/**
* Render a folder from extension templates into devland.
* Needs a path (to a folder) relative to the path of the file where render() is called
*
* @param {string} templatePath (relative path to folder to render in app)
* @param {object} scope (optional; rendering scope variables)
*/
render(templatePath, scope) {
const dir = getCallerPath(1)
const source = path.resolve(dir, templatePath)
const rawCopy = !scope || Object.keys(scope).length === 0
if (!fs.existsSync(source)) {
this.logger.warn(`render() - cannot locate ${templatePath}. Skipping...`)
return
}
if (!fs.lstatSync(source).isDirectory()) {
this.logger.warn(
`render() - "${templatePath}" is a file instead of folder. Skipping...`
)
return
}
this.#hooks.renderFolders.push({
source,
rawCopy,
scope
})
}
/**
* Render a file from extension template into devland
* Needs a path (to a file) relative to the path of the file where renderFile() is called
*
* @param {string} relativeSourcePath (file path relative to the folder from which the install script is called)
* @param {string} relativeTargetPath (file path relative to the root of the app -- including filename!)View on GitHub (pinned to 4841521b5f)
Solutions
- Switch to api.renderFile(relativeSourcePath, relativeTargetPath, scope) for single files.
- If a folder was intended, create the directory with the template contents at that path.
- Check for missing file extensions in the path that make a file look like a folder name.
Example fix
// before
api.render('./template/banner')
// after: single file rendering
api.renderFile('./template/banner.html', 'src/banner.html', { scope: 1 }) Defensive patterns
Strategy: validation
Validate before calling
const fs = require('fs');
const path = require('path');
const src = path.resolve(__dirname, templatePath);
if (fs.existsSync(src) && !fs.statSync(src).isDirectory()) {
api.renderFile(templatePath, targetPath, scope);
} else {
api.render(templatePath, scope);
} Type guard
function isDirectory(baseDir, p) {
const fs = require('fs');
const full = require('path').resolve(baseDir, p);
return fs.existsSync(full) && fs.statSync(full).isDirectory();
} Prevention
- Use api.render() only for directories; use api.renderFile() for files.
- Verify path shapes during extension development in a scratch app.
When it happens
Trigger: api.render('./template') where './template' resolves to an existing file (e.g. './template' is a file named 'template' with no extension, or the author meant a single file).
Common situations: Extension author passing a single template file to render() instead of renderFile(); a symlink or naming collision making the path point to a file.
Related errors
- renderFile() - "${relativeSourcePath}" is a folder instead o
- render() - cannot locate ${templatePath}. Skipping...
- Could not resolve an existing ancestor for "${target}"
- Build output directory must be a non-empty path
- Project directory must be a non-empty path
AI-assisted analysis of quasarframework/quasar@4841521b5f (2026-08-30).
Data as JSON: /api/errors/5f8eb7ad9e729451.
Report an issue: GitHub.