{"record":{"id":"8f8089321d436cf0","repo":"quasarframework/quasar","slug":"renderfile-relativesourcepath-is-a-folder","errorCode":null,"errorMessage":"renderFile() - \"${relativeSourcePath}\" is a folder instead of a file. Skipping...","messagePattern":"renderFile\\(\\) - \"(.+?)\" is a folder instead of a file\\. Skipping\\.\\.\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"app-vite/lib/app-extension/api-classes/InstallAPI.js","lineNumber":290,"sourceCode":"   *\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!)\n   * @param {object} scope (optional; rendering scope variables)\n   */\n  renderFile(relativeSourcePath, relativeTargetPath, scope) {\n    const dir = getCallerPath(1)\n    const sourcePath = path.resolve(dir, relativeSourcePath)\n    const targetPath = this.resolve.app(relativeTargetPath)\n    const rawCopy = !scope || Object.keys(scope).length === 0\n\n    if (!fs.existsSync(sourcePath)) {\n      this.logger.warn(\n        `renderFile() - cannot locate ${relativeSourcePath}. Skipping...`\n      )\n      return\n    }\n    if (fs.lstatSync(sourcePath).isDirectory()) {\n      this.logger.warn(\n        `renderFile() - \"${relativeSourcePath}\" is a folder instead of a file. Skipping...`\n      )\n      return\n    }\n\n    this.#hooks.renderFiles.push({\n      sourcePath,\n      targetPath,\n      rawCopy,\n      scope,\n      overwritePrompt: true\n    })\n  }\n\n  /**\n   * Add a message to be printed after App CLI finishes up install.\n   *\n   * @param {string} msg","sourceCodeStart":272,"sourceCodeEnd":308,"githubUrl":"https://github.com/quasarframework/quasar/blob/4841521b5f635a971eb9e2710e5542efd194691b/app-vite/lib/app-extension/api-classes/InstallAPI.js#L272-L308","documentation":"api.renderFile() renders a single FILE; this warning fires when the resolved source path exists but is a DIRECTORY. The call is skipped — use api.render() for folders.","triggerScenarios":"api.renderFile('./templates', 'src/templates') where './templates' resolves to an existing directory instead of a file.","commonSituations":"Extension author passing a folder path to renderFile(); trailing-slash or shorthand paths that point at directories.","solutions":["Use api.render(templatePath, scope) for directories.","Point relativeSourcePath at the specific file inside the folder.","Check for typos where a directory name was given instead of a filename."],"exampleFix":"// before\napi.renderFile('./templates', 'src/templates')\n// after: render the whole folder\napi.render('./templates')","handlingStrategy":"validation","validationCode":"const fs = require('fs');\nconst path = require('path');\nconst src = path.resolve(__dirname, relativeSourcePath);\nif (fs.existsSync(src) && fs.statSync(src).isDirectory()) {\n  api.render(relativeSourcePath, scope);\n} else {\n  api.renderFile(relativeSourcePath, relativeTargetPath, scope);\n}","typeGuard":"function isFile(baseDir, p) {\n  const fs = require('fs');\n  const full = require('path').resolve(baseDir, p);\n  return fs.existsSync(full) && fs.statSync(full).isFile();\n}","tryCatchPattern":null,"preventionTips":["Route folders to api.render() and files to api.renderFile().","Check the resolved path's stat type before choosing which API to call."],"tags":["app-extension","renderfile","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"}