overleaf/overleaf · error

folder_not_found

folder_not_found

Error message

folder_not_found

What it means

upsertDoc resolves the target folder via ProjectLocator.findElement({ type: 'folder', element_id: folderId }). If that lookup raises Errors.NotFoundError, it is rethrown as a plain Error with message 'folder_not_found', signalling the destination folder does not exist in the project.

Source

Thrown at services/web/app/src/Features/Project/ProjectEntityUpdateHandler.mjs:401

  },
})

const upsertDoc = wrapWithLock(
  async function (projectId, folderId, docName, docLines, source, userId) {
    if (!SafePath.isCleanFilename(docName)) {
      throw new Errors.InvalidNameError('invalid element name')
    }
    let element, folderPath
    try {
      ;({ element, path: folderPath } =
        await ProjectLocator.promises.findElement({
          project_id: projectId,
          element_id: folderId,
          type: 'folder',
        }))
    } catch (error) {
      if (error instanceof Errors.NotFoundError) {
        throw new Error('folder_not_found')
      }
      throw error
    }

    if (element == null) {
      throw new Error("Couldn't find folder")
    }

    const existingDoc = element.docs.find(({ name }) => name === docName)
    const existingFile = element.fileRefs.find(({ name }) => name === docName)
    if (existingFile) {
      const doc = new Doc({ name: docName })
      const filePath = `${folderPath.fileSystem}/${existingFile.name}`
      const { rev } = await DocstoreManager.promises.updateDoc(
        projectId.toString(),
        doc._id.toString(),
        docLines,
        0,

View on GitHub (pinned to 28ad3b03b7)

Solutions

  1. Re-fetch the folder (or project tree) to confirm folderId exists before upserting
  2. Fall back to the project root folder when the target folder is missing
  3. Catch the 'folder_not_found' error and recreate the folder via mkdirp before retrying
  4. Ensure folderId belongs to the same projectId

Example fix

// before
await handler.promises.upsertDoc(projectId, folderId, name, lines, source, userId)
// after
try {
  await handler.promises.upsertDoc(projectId, folderId, name, lines, source, userId)
} catch (err) {
  if (err.message === 'folder_not_found') {
    const root = await getRootFolder(projectId)
    await handler.promises.upsertDoc(projectId, root._id, name, lines, source, userId)
  } else throw err
}
Defensive patterns

Strategy: try-catch

Validate before calling

const folder = await ProjectLocator.promises.findElement({ project_id: projectId, element_id: folderId, type: 'folder' }).catch(() => null)
if (folder == null) throw new Error('target folder does not exist')

Type guard

const folderExists = (result) => result != null && result.element != null

Try / catch

try {
  await handler.promises.upsertDoc(projectId, folderId, docName, lines, source, userId)
} catch (err) {
  if (err.message === 'folder_not_found') {
    const [rootFolder] = await ProjectLocator.promises.rootFolder({ project_id: projectId })
    return handler.promises.upsertDoc(projectId, rootFolder._id, docName, lines, source, userId)
  }
  throw err
}

Prevention

When it happens

Trigger: Calling upsertDoc with a folderId that was deleted, belongs to another project, or is a stale/invalid ObjectId; passing null folderId where the lookup treats it as missing.

Common situations: Clients caching folder IDs across project copies; concurrent deletion of the target folder; scripts referencing folder IDs from an old project snapshot.

Related errors


AI-assisted analysis of overleaf/overleaf@28ad3b03b7 (2026-09-03). Data as JSON: /api/errors/d674ddc662a7e024. Report an issue: GitHub.