Hello Obsidian Community,
I’m working on a QuickAdd user script to automate the creation of a complex task structure in my vault, but I’m encountering a persistent “File already exists” error, despite my efforts to ensure unique filenames.
What I’m Trying to Achieve:
I want to create a script that:
- Creates a new task folder in the
_31 - TASKS
directory.- The folder name includes the current date and the task title, formatted as
YYYY-MM-DD - Task Title
.
- The folder name includes the current date and the task title, formatted as
- Creates a note inside the new folder with the same name as the folder (for folder note compatibility).
- Applies the
Task-Page.md
template to this note.
- Applies the
- Creates several subfolders within the task folder:
_11 - fleeting notes of task
_12 - resources notes of task
_13 - permanent notes of task
__va
- Creates index notes (folder notes) within each subfolder using appropriate templates:
- For example,
Fleeting-Board-Page.md
for the fleeting notes subfolder.
- For example,
Example Structure:
If I create a task titled “Write Project Proposal” on 2023-10-15, the script should generate:
_31 - TASKS/
└── 2023-10-15 - Write Project Proposal/
├── 2023-10-15 - Write Project Proposal.md (applies Task-Page.md template)
├── _11 - fleeting notes of task/
│ └── _11 - fleeting notes of task.md (applies Fleeting-Board-Page.md template)
├── _12 - resources notes of task/
│ └── _12 - resources notes of task.md (applies Resource-Board-Page.md template)
├── _13 - permanent notes of task/
│ └── _13 - permanent notes of task.md (applies Permanent-Board-Page.md template)
└── __va/
└── __va.md (applies VA-Board-Page.md template)
The Issue:
When I run my script, I receive the following error:
Note Creation Error: Error: File already exists.
at t.<anonymous> (app.js:1:732794)
at app.js:1:237228
at Object.next (app.js:1:237333)
at a (app.js:1:236051)
What I’ve Tried:
- Ensuring Unique Filenames:
- I attempted to append a number to the task title if a file with the same name already exists, using a loop to check for existing files.
- Verifying Template Paths:
- Confirmed that all template files (
Task-Page.md
,Fleeting-Board-Page.md
, etc.) exist in the_90 - META/Templates/
directory.
- Confirmed that all template files (
- Checking the Script for Errors:
- Reviewed the script for syntax errors and logical issues.
Despite these efforts, the error persists, and the script does not proceed as expected.
My Script:
Here’s the current version of my script:
// create-task-page-in-global.js
module.exports = async (params) => {
const { app, quickAddApi } = params;
const { moment, Notice } = window;
const { vault, workspace } = app;
// Define normalizePath function
function normalizePath(path) {
return path.replace(/\\/g, "/");
}
try {
// Prompt the user for the task title
let taskTitle = await quickAddApi.inputPrompt("Enter task title:");
if (!taskTitle) {
new Notice("No task title provided.", 3000);
return;
}
// Ensure task title is unique
const currentDate = moment().format("YYYY-MM-DD");
let taskFolderName = `${currentDate} - ${taskTitle}`;
let taskFolderPath = normalizePath(`_31 - TASKS/${taskFolderName}`);
let taskFileName = `${currentDate} - ${taskTitle}.md`;
let newNotePath = normalizePath(`${taskFolderPath}/${taskFileName}`);
let fileCount = 1;
while (vault.getAbstractFileByPath(newNotePath)) {
taskTitle = `${taskTitle} (${fileCount})`;
taskFolderName = `${currentDate} - ${taskTitle}`;
taskFolderPath = normalizePath(`_31 - TASKS/${taskFolderName}`);
taskFileName = `${currentDate} - ${taskTitle}.md`;
newNotePath = normalizePath(`${taskFolderPath}/${taskFileName}`);
fileCount++;
}
// Ensure the target folder exists; if not, create it
await createFolderIfNotExists(taskFolderPath);
// Read the content from the Task-Page template
const templatePath = normalizePath("_90 - META/Templates/Task-Page.md");
const templateFile = vault.getAbstractFileByPath(templatePath);
if (!templateFile) {
new Notice(`Template file "${templatePath}" not found.`, 5000);
console.error(`Template file "${templatePath}" does not exist.`);
return;
}
// Create subfolders and their notes
const subfolders = [
{ name: "_11 - fleeting notes of task", template: "Fleeting-Board-Page.md" },
{ name: "_12 - resources notes of task", template: "Resource-Board-Page.md" },
{ name: "_13 - permanent notes of task", template: "Permanent-Board-Page.md" },
{ name: "__va", template: "VA-Board-Page.md" }
];
await Promise.all(subfolders.map(async (subfolder) => {
const subfolderPath = normalizePath(`${taskFolderPath}/${subfolder.name}`);
await createFolderIfNotExists(subfolderPath);
const indexFileName = `${subfolder.name}.md`;
const indexFilePath = normalizePath(`${subfolderPath}/${indexFileName}`);
const subTemplatePath = normalizePath(`_90 - META/Templates/${subfolder.template}`);
const subTemplateFile = vault.getAbstractFileByPath(subTemplatePath);
if (!subTemplateFile) {
new Notice(`Template file "${subTemplatePath}" not found.`, 5000);
console.error(`Template file "${subTemplatePath}" does not exist.`);
return; // Skip this subfolder if the template is not found
}
let subTemplateContent = await vault.read(subTemplateFile);
subTemplateContent = replacePlaceholders(subTemplateContent, subfolder.name, currentDate);
await vault.create(indexFilePath, subTemplateContent);
}));
// Replace placeholders in the main task template after subfolders are created
let templateContent = await vault.read(templateFile);
templateContent = replacePlaceholders(templateContent, taskTitle, currentDate);
// Create the new note with the template content
await vault.create(newNotePath, templateContent);
// Open the newly created main task note
const file = vault.getAbstractFileByPath(newNotePath);
if (file) {
const leaf = workspace.getLeaf(false);
await leaf.openFile(file);
new Notice(`Task note "${taskTitle}" created successfully!`, 3000);
} else {
new Notice(`Failed to open the new note "${taskTitle}".`, 5000);
console.error(`Failed to retrieve the newly created file "${newNotePath}".`);
}
} catch (error) {
new Notice(`Error creating task note: ${error.message}`, 5000);
console.error("Note Creation Error:", error);
}
// Helper function to create a folder if it doesn't exist
async function createFolderIfNotExists(folderPath) {
try {
if (!vault.getAbstractFileByPath(folderPath)) {
await vault.createFolder(folderPath);
}
} catch (error) {
new Notice(`Error creating folder: ${error.message}`, 5000);
console.error("Folder Creation Error:", error);
}
}
// Helper function to replace placeholders in the template
function replacePlaceholders(templateContent, title, currentDate) {
const titlePlaceholder = /<% tp\.file\.title %>/g;
const datePlaceholder = /<% tp\.date\.now\("YYYY-MM-DD"\) %>/g;
const cursorPlaceholder = /<% tp\.file\.cursor\(\) %>/g;
return templateContent
.replace(titlePlaceholder, title)
.replace(datePlaceholder, currentDate)
.replace(cursorPlaceholder, ""); // Remove cursor placeholder for now
}
};
Templates:
- Task-Page.md and other templates contain Templater placeholders like
<% tp.file.title %>
. The script includes a function to replace these placeholders.
Error Message:
Note Creation Error: Error: File already exists.
at t.<anonymous> (app.js:1:732794)
at app.js:1:237228
at Object.next (app.js:1:237333)
at a (app.js:1:236051)
Request for Help:
I’m unsure why this error occurs, as I’m attempting to ensure that filenames are unique before creating them. Is there something I’m missing in how Obsidian’s vault.create()
method works, or is there a better way to handle file creation and uniqueness?
Any insights or suggestions would be greatly appreciated!
Thank you!