{"record":{"id":"5f8eb7ad9e729451","repo":"quasarframework/quasar","slug":"render-templatepath-is-a-file-instead-of","errorCode":null,"errorMessage":"render() - \"${templatePath}\" is a file instead of folder. Skipping...","messagePattern":"render\\(\\) - \"(.+?)\" is a file instead of folder\\. Skipping\\.\\.\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"app-vite/lib/app-extension/api-classes/InstallAPI.js","lineNumber":256,"sourceCode":"\n  /**\n   * Render a folder from extension templates into devland.\n   * Needs a path (to a folder) relative to the path of the file where render() is called\n   *\n   * @param {string} templatePath (relative path to folder to render in app)\n   * @param {object} scope (optional; rendering scope variables)\n   */\n  render(templatePath, scope) {\n    const dir = getCallerPath(1)\n    const source = path.resolve(dir, templatePath)\n    const rawCopy = !scope || Object.keys(scope).length === 0\n\n    if (!fs.existsSync(source)) {\n      this.logger.warn(`render() - cannot locate ${templatePath}. Skipping...`)\n      return\n    }\n    if (!fs.lstatSync(source).isDirectory()) {\n      this.logger.warn(\n        `render() - \"${templatePath}\" is a file instead of folder. Skipping...`\n      )\n      return\n    }\n\n    this.#hooks.renderFolders.push({\n      source,\n      rawCopy,\n      scope\n    })\n  }\n\n  /**\n   * Render a file from extension template into devland\n   * Needs a path (to a file) relative to the path of the file where renderFile() is called\n   *\n   * @param {string} relativeSourcePath (file path relative to the folder from which the install script is called)\n   * @param {string} relativeTargetPath (file path relative to the root of the app -- including filename!)","sourceCodeStart":238,"sourceCodeEnd":274,"githubUrl":"https://github.com/quasarframework/quasar/blob/4841521b5f635a971eb9e2710e5542efd194691b/app-vite/lib/app-extension/api-classes/InstallAPI.js#L238-L274","documentation":"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.","triggerScenarios":"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).","commonSituations":"Extension author passing a single template file to render() instead of renderFile(); a symlink or naming collision making the path point to a file.","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."],"exampleFix":"// before\napi.render('./template/banner')\n// after: single file rendering\napi.renderFile('./template/banner.html', 'src/banner.html', { scope: 1 })","handlingStrategy":"validation","validationCode":"const fs = require('fs');\nconst path = require('path');\nconst src = path.resolve(__dirname, templatePath);\nif (fs.existsSync(src) && !fs.statSync(src).isDirectory()) {\n  api.renderFile(templatePath, targetPath, scope);\n} else {\n  api.render(templatePath, scope);\n}","typeGuard":"function isDirectory(baseDir, p) {\n  const fs = require('fs');\n  const full = require('path').resolve(baseDir, p);\n  return fs.existsSync(full) && fs.statSync(full).isDirectory();\n}","tryCatchPattern":null,"preventionTips":["Use api.render() only for directories; use api.renderFile() for files.","Verify path shapes during extension development in a scratch app."],"tags":["app-extension","render","wrong-argument-type","path"],"backgroundTag":"wrong-api-for-path-type","analyzedSha":"4841521b5f635a971eb9e2710e5542efd194691b","analyzedAt":"2026-08-30T01:13:14.944Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}