CherryHQ/cherry-studio · error · Error

Failed to read required agent prompt file: ${filePath}

Error message

Failed to read required agent prompt file: ${filePath}

What it means

Thrown by PromptBuilder.readCachedFile (failOnError=true) as a wrapper around any underlying failure to read a required prompt file — the path is not a regular file, lstat throws (e.g. ENOENT, EACCES), or reading the file content fails. The original error is attached via Error cause so the real reason is preserved. This is the hard-fail path for prompt files the agent cannot run without.

Source

Thrown at src/main/ai/agents/prompt.ts:272

  }

  /**
   * Read a file with mtime-based caching. Returns undefined if the file does not exist.
   */
  private async readCachedFile(filePath: string, expectedRoot: string, failOnError: true): Promise<string>
  private async readCachedFile(
    filePath: string,
    expectedRoot?: string,
    failOnError?: false
  ): Promise<string | undefined>
  private async readCachedFile(
    filePath: string,
    expectedRoot = path.dirname(filePath),
    failOnError = false
  ): Promise<string | undefined> {
    const fail = (error: unknown): undefined => {
      if (failOnError) {
        throw new Error(`Failed to read required agent prompt file: ${filePath}`, { cause: error })
      }
      return undefined
    }

    let fileStat
    try {
      fileStat = await lstat(filePath)
      if (!fileStat.isFile() || fileStat.isSymbolicLink()) {
        logger.warn('Ignoring non-regular file in agent prompt data', { path: filePath })
        return fail(new Error('Path is not a regular file'))
      }
    } catch (error) {
      return fail(error)
    }

    try {
      const [resolvedRoot, resolvedFile] = await Promise.all([realpath(expectedRoot), realpath(filePath)])
      const relative = path.relative(resolvedRoot, resolvedFile)

View on GitHub (pinned to 726446b54c)

Solutions

  1. Inspect error.cause for the real reason (ENOENT/EACCES/'not a regular file').
  2. Confirm the file exists at the path and is a readable regular file: `ls -la <filePath>`.
  3. Fix permissions or ownership so the app process can read it.
  4. Reinstall/restore the prompt resource from packaging, or mark it optional by calling readCachedFile without failOnError.

Example fix

// before: required prompt file missing or unreadable
await builder.readCachedFile('/app/prompts/required.md', root, true)

// after: ensure the file ships and is readable, or treat as optional
await fs.promises.access(filePath, fs.constants.R_OK)
await builder.readCachedFile(filePath, root, true)
Defensive patterns

Strategy: try-catch

Validate before calling

import { access, constants, lstat } from 'node:fs/promises'
async function canReadPromptFile(p: string): Promise<boolean> {
  try {
    await access(p, constants.R_OK)
    const s = await lstat(p)
    return s.isFile() && !s.isSymbolicLink()
  } catch {
    return false
  }
}
if (!(await canReadPromptFile(filePath))) {
  // skip or fail with a clearer message before calling readCachedFile(failOnError=true)
}

Type guard

function isReadableRegularFile(stat: import('node:fs').Stats): boolean {
  return stat.isFile() && !stat.isSymbolicLink()
}

Try / catch

try {
  const content = await builder.readCachedFile(filePath, root, true)
} catch (e) {
  if (e instanceof Error && /Failed to read required agent prompt file/.test(e.message)) {
    // inspect e.cause for ENOENT/EACCES/'not a regular file'
    logger.error('Required prompt file unreadable', { filePath, cause: (e as Error & { cause?: unknown }).cause })
  } else throw e
}

Prevention

When it happens

Trigger: readCachedFile(filePath, expectedRoot, failOnError=true) is called and the file is missing, not readable, not a regular file, or the read itself throws.

Common situations: A required prompt file was deleted or never installed; file permissions deny the app read access; the path points at a directory or symlink; packaging omitted required prompt resources; ENOENT after a partial upgrade.

Related errors


AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12). Data as JSON: /api/errors/4e85afed4da3630a. Report an issue: GitHub.